Abstract

This thesis builds upon previous literature for modeling value-at-risk (defined as an x% quantile of an asset’s daily returns) using non-linear ARMA terms by adding exchange-traded funds (ETFs) as explanatory variables that are combined into principal component vectors at the forecast origin. Combining these principal component vectors with transformations of lagged autoregressive response variables results in a model that produces similar predictive accuracy during periods of relatively low volatility along with more insight into the drivers of the changes in the response variable. In fact, one insight gained from the new model is a method of detecting changepoints in the economy by measuring the angle between resultant vectors calculated from the combination of principal component vectors during different time periods. This method, along with analysis of the statistical significance of the lagged ETFs, allows for insight into changes in the underlying economy.

Background and Introduction

When modeling financial time series, simply considering the mean and the variance is insufficient. In fact, modeling a 1% or a 5% quantile of daily returns is a way to understand what happens on the worst days and to have a clearer picture of what might happen during a downturn. Indeed, finance theory suggests that a primary reason why the S&P 500, which is a market-capitalization weighted index composed of the 500-largest publicly traded companies in the United States, has earned 6.8% inflation-adjusted pre-tax return with dividend reinvestment from January 1871 through April 2020 (CITE) is because of the risk of a significant downturn. Kerry Pechter at Forbes describes it as a premium for the fact that “stocks are riskier” and “more prone to price fluctuations in the short run” compared to lower risk investments (CITE). While the long-run picture of stock returns is a bit clearer, the short-run is a huge question - an investment manager using financial leverage to magnify returns (positive or negative) that could leave them in dire straits if their investments fell rapidly, despite a sound long-run strategy.

While there are other ways to understand and measure downside risk, a commonly accepted means is using value-at-risk (VaR). The metric is understood as follows: a one-day 1% VaR of -10% for a portfolio means that the portfolio will lose at least 10% of its’ value on the 1% worst trading days. A major advantage of VaR is that it distills a distribution of returns into one number. As such, VaR is often used in stress testing by regulatory agencies in the United States, the United Kingdom, and Europe (CITE).

Many of the approaches for modeling VaR rely on a semiparametric or a nonparametric historical simulation (ADD CITATION - BOUDOUKH). According to Robert Engle and Simone Manganelli in a 2004 paper, these methods are usually chosen for “empirical justifications rather than on sound statistical theory” (ADD CITATION - ENGLE). As such, they propose a framework called CAViaR that forecasts the VaR quantile directly using a conditional autoregressive quantile specification. This approach builds upon the statistical literature that extends linear quantile models to settings amenable to financial modeling, such as with heteroskedastic and nonstationary error distributions (ADD CITATION - KOENKER, PORTNOY).

Methods Used

A common problem in statistical analysis occurs when a training sample is significantly different than that of the test sample. Initial motivations for this paper involved analyzing two stocks - Amazon (ticker: AMZN) and Proctor & Gamble (ticker: PG) and their performance during the great recession. A relevant question of a financial institution would understandably be how their risk model performed during 2008, a highly volatile period which was driven by the “worst financial crisis since the Great Depression” according to Gary Becker (CITE), a Nobel-prize winning Economist. Interestingly, the forecast for Amazon was fairly accurate whereas the forecast for PG was not. One reason for this could be the fact that a stock like Amazon was highly volatile during the training sample, which included data from previous years (HOW MANY?), but PG was fairly calm. How would it be possible for a univariate model such as CAViaR, that does not explicitly account for other factors, to forecast well? What if a volatile stock such as AMZN was included into the forecast for PG - would it improve the forecast?

Thus, the idea of combining stocks into a multivariate setting to capture correlations and better forecast risk was formed. A natural choice appeared to be the diffusion index model, originally developed by Stock and Watson for predicting conditional means [TWO CITATIONS]. The model for forecasting the conditional mean is specified below.

Diffusion Index Model

A useful means of predicting stock movements in the future is the Stock and Watson diffusion index. The model is outlined below, which is adapted from Multivariate Time Series Analysis With R and Financial Applications by Ruey S. Tsay [ADD CITATION].

There are two relevant equations:

\[ \boldsymbol{z_t} = \boldsymbol{Lf_t} + \boldsymbol{\epsilon_t} \]

and

\[ y_{t+h} = \boldsymbol{\beta^\prime f_t} + \boldsymbol{e_{t+h}} \]

In the first equation \(\boldsymbol{z_t} = (z_{1t}, ...., z_{kt})^\prime\) is an observed time series with mean 0, \(\boldsymbol{f_t}\) is an m-dimensional vector of common factors with mean 0 and identity covariance matrix, \(\boldsymbol{L}\) is a \(k\) x \(m\) loading matrix, and \(\boldsymbol{\epsilon_t}\) is a i.i.d. sequence of random vectors with mean 0 and covariance matrix \(\boldsymbol{\Sigma_e}\).

In the second equation, which represents the h-step ahead prediction based on \(\boldsymbol{f_t}\), \(y_t\) is the scalar time series of interest, \(h\) is the forecast horizon, \(\boldsymbol{\beta}\) represents the vector of coefficients, and \(e_t\) is a sequence of uncorrelated random variables with mean 0 and constant variance.

To model the data, principal component analysis is performed on the covariates described below to obtain an estimate of \(\boldsymbol{f_t}\). Then the \(\boldsymbol{\beta}\) coefficients are estimated using ordinary least squares.

Univariate CAViaR Model

However, work needed to be done to align the diffusion index model with the CAViaR model, which is defined below. The following variables are required for use in the CAViaR model:

[DESCRIPTION OF VARIABLES]

Adaptive CAViaR Model

\[ f_t(\beta_1) = f_{t-1}(\beta_1) + \beta_1\left[\left(1+ \exp(G[y_{t-1} - f_{t-1}(\beta_1)]) \right)^{-1} - \theta \right] \]

Symmetric Absolute Value CAViaR Model

\[ f_t(\boldsymbol{\beta}) = \beta_1 + \beta_2f_{t-1}(\boldsymbol{\beta}) + \beta_3|y_{t-1}| \]

Asymmetric Slope CAViaR Model

\[ f_t(\boldsymbol{\beta}) = \beta_1 + \beta_2f_{t-1}(\boldsymbol{\beta}) + \beta_3(y_{t-1})^+ + \beta_4(y_{t-1})^- \]

Indirect GARCH (1,1) CAViaR Model

\[ f_t(\boldsymbol{\beta}) = (\beta_1 + \beta_2f_{t-1}^2(\boldsymbol{\beta}) + \beta_3y_{t-1}^2)^{1/2} \]

Multivariate CAViaR Model

The multivariate CAViaR model takes inspiration from the models described above in several specifications. The general model form looks like the specification below.

VAR = INTERCEPT + PAST VALUES + AR COMPONENT + ERROR

Multivariate CAViaR: No Lags Model

VAR = INTERCEPT + PAST VALUES + ERROR

Multivariate CAViaR with Autoregressive Terms Added

VAR = INTERCEPT + PAST VALUES + AR COMPONENT + ERROR

Multivariate CAViaR with Symmetric Absolute Value Autoregressive Terms Added

VAR = INTERCEPT + PAST VALUES + SAV AR COMPONENT + ERROR

Multivariate CAViaR with Asymmetric Slope Autoregressive Terms Added

VAR = INTERCEPT + PAST VALUES + AS AR COMPONENT + ERROR

Fitting the Models

To fit the models, an optimal value of \(m\) diffusion indices and \(p\) autoregressive terms are added (or \(2p\) in the case of the asymmetric slope model). The optimal values of these parameters are arrived at using a validation dataset. In all of the runs below, there are a total of 5 years of trading days, or about 1,260 days assuming 252 trading days a year. The adjusted closing prices are logged and differenced, shortening the dataset by one. After doing this, the last 250 data points are reserved as test data, and the 250 data points before that are used as a validation set. Measured by the loss function written out below, the values of \(p\) and \(m\) that minimize losses are chosen and the optimal model is refit over both the training and the validation data combined and then evaluated on the test data. Note that this an optimal model is chosen for each of the four multivariate CAViaR specifications described above, so there are 4 optimal sets of \(p\) and \(m\) chosen for each set of model. Thus, there are 8 models compared on the test data - 4 univariate CAViaR models and 4 multivariate CAViaR models.

[LOSS FUNCTION]

Data Used

The response variable used in this analysis is SPY, which is an exchange-traded fund that aims to track the performance of the S&P 500, which is discussed above. It is broadly used as a bellwether of the U.S. economy (CITE), and has the advantage of avoiding survivorship bias - while an individual stock might go bankrupt or merge with another, it’s reasonable to assume that these issues do not apply with an ETF.

Following this logic, there are several classes of response variables used in this analysis. The first group is a set of U.S. sector ETFs obtained from Seeking Alpha [CITE] using the link below. As with the response variable, these ETFs were publicly traded throughout the Great Recession.

  1. Utilities (XLU)
  2. Consumer Staples (XLP)
  3. Healthcare (XLV)
  4. Technology (XLK)
  5. Consumer Discretionary (XLY)
  6. Industrial (XLI)
  7. Financial Services (XLF)
  8. Basic Materials (XLB)
  9. Energy (XLE)

The second is Global Sector ETFs, also obtained from Seeking Alpha. The rationale for including these is that perhaps some global exposure is useful in understanding the broader market.

  1. Utilities (JXI)
  2. Consumer Staples (KXI)
  3. Healthcare (IXJ)
  4. Telecommunications (IXP)
  5. Technology (IXN)
  6. Consumer Discretionary (RXI)
  7. Industrial (EXI)
  8. Financial Services (IXG)
  9. Basic Materials (MXI)
  10. Energy (IXC)

The third is bond ETFs, also obtained from [CITE]. Like the previous two, these ETFs potentially contain forward-looking information about the stock market. Link below:

  1. iShares 1-3 Year Treasury Bond Fund (SHY)
  2. iShares 7-10 Year Treasury Bond Fund (IEF)
  3. iShares 20+ Year Treasury Bond Fund (TLT)
  4. iShares iBoxx $ Investment Grade Corporate Bond ETF (LQD)

Lastly, all of the above are run together. In each run, the explanatory variables are lagged to avoid look-ahead bias. All of the runs analyze the difference of the log of the adjusted closing price. The reason for using the differenced log is that it closely approximates the percentage change of the price for small changes. Also,

Results

# Read in relevant libraries
library(microbenchmark)
library(data.table)
package ‘data.table’ was built under R version 3.5.2data.table 1.12.2 using 1 threads (see ?getDTthreads).  Latest news: r-datatable.com
library(quantmod)
package ‘quantmod’ was built under R version 3.5.2Loading required package: xts
Loading required package: zoo
package ‘zoo’ was built under R version 3.5.2
Attaching package: ‘zoo’

The following objects are masked from ‘package:base’:

    as.Date, as.Date.numeric


Attaching package: ‘xts’

The following objects are masked from ‘package:data.table’:

    first, last

Loading required package: TTR
Version 0.4-0 included new data defaults. See ?getSymbols.
library(ggplot2)
package ‘ggplot2’ was built under R version 3.5.2
library(tseries)
package ‘tseries’ was built under R version 3.5.2
    ‘tseries’ version: 0.10-47

    ‘tseries’ is a package for time series analysis and computational finance.

    See ‘library(help="tseries")’ for details.
library(zoo)
library(magrittr)
library(dplyr)
package ‘dplyr’ was built under R version 3.5.2
Attaching package: ‘dplyr’

The following objects are masked from ‘package:xts’:

    first, last

The following objects are masked from ‘package:data.table’:

    between, first, last

The following objects are masked from ‘package:stats’:

    filter, lag

The following objects are masked from ‘package:base’:

    intersect, setdiff, setequal, union
library(kableExtra)
package ‘kableExtra’ was built under R version 3.5.2
Attaching package: ‘kableExtra’

The following object is masked from ‘package:dplyr’:

    group_rows
library(formattable)
library(quantreg)
package ‘quantreg’ was built under R version 3.5.2Loading required package: SparseM

Attaching package: ‘SparseM’

The following object is masked from ‘package:base’:

    backsolve
library(MTS)

Attaching package: ‘MTS’

The following object is masked from ‘package:TTR’:

    VMA
library(plot3D)
package ‘plot3D’ was built under R version 3.5.2
library(citr)
package ‘citr’ was built under R version 3.5.2
library(formattable)
# Set up working directory
# setwd("~/Documents/GitHub/CaviaR")
# source('caviar_SM.R')
source('~/Documents/GitHub/CaviaR/caviar_SM.R')
Loading required package: Rcpp
package ‘Rcpp’ was built under R version 3.5.2The working directory was changed to /Users/stevenmoen/Documents/GitHub/CAViaR inside a notebook chunk. The working directory will be reset when the chunk is finished running. Use the knitr root.dir option in the setup chunk to change the working directory for notebook chunks.
# This code below is for use in the CAViaR sections.
# Here is code that I'll wrap some parts in to avoid superfluous output
quiet <- function(x) { 
  sink(tempfile()) 
  on.exit(sink()) 
  invisible(force(x)) 
} 
#' This is a function which pulls data for use in the CAViaR model
#'
#' @param symbol - symbol to pull
#' @param compl_case - defaults to true...only includes complete cases in the data
#' @param adj_close - use adjusted closing prices. Default is yes.
#' @param log_return - use log return? Default is yes.
#'
#' @return - a data frame which can be fed into later functions
#' @export
#'
#' @examples - data_pull("SPY")
data_pull = function(symbol, compl_case = 1, adj_close = 1, log_return = 1, start_date = "1900-01-01", end_date = Sys.Date()){
  # Pull in data from quantmod
  response_pull = getSymbols(symbol, auto.assign = FALSE, from = start_date, to = end_date)
  # Get adjusted closing price
  if (adj_close == TRUE){
    df = Ad(response_pull)
  } else {
    df = Cl(response_pull)
  }
  # Return complete cases only 
  if (compl_case == TRUE){
    df = df[complete.cases(df), ]
  } else{
    df = df
  }
  # Calculate log return of data
  if (log_return == TRUE){
    lr = log(df[,1]/shift(df[,1], 1, type = "lag"))
    # Combine data
    df_out = cbind(df, lr)
    # Rename the data 
    colnames(df_out) <- c(sym=symbol, paste0(symbol, "_log_return"))
  } else{
    df_out = df
  }
  # Return data
  return(df_out)
}
#' Pull the data and run the CAViaR function on it
#'
#' @param input_data - data to use in the function
#' @param range_data - range of the data to use
#'
#' @return - a list of values from the caviar function
#' @export
#'
#' @examples - caviar_pull(spy)
caviar_pull = function(input_data, range_data = (2:dim(input_data)[1])){
  # Run the caviar data
  caviar <- caviarOptim(input_data[range_data,2])
  return(caviar)
}
#' Function for producing rolling predictions
#' Model 1 = Symmetric Absolute Value, 2 = Asymmetric slope, 3 = Indirect GARCH, 4 = Adaptive
#'
#' @param input_data - input data from the previous function
#' @param range_data - range of the data to consider
#' @param nfcst - number of forecasts to make
#' @param model - model to use (integers 1 through 4). Defaults to 1. 
#' @param level - level of significance to use.
#' @param G - argument for the k parameter in the 4th model (adaptive). Default is 5
#'
#' @return - an xts object which contains rolling CAViaR predictions
#' @export
#'
#' @examples - rolling_predictions(spy, nfcst = 22)
rolling_predictions = function(input_data, range_data = (2:dim(input_data)[1]), nfcst = 250, model =1, level = 0.01, G = 5, col = 2){
  # Run the varpredict function
  varpredict <- rollapplyr(input_data[range_data,col], length(range_data) - nfcst, caviarOptim, model, level, predict = 1, k = G) %>% lag
  # Eliminate NAs
  # pred_no_na = na.omit(varpredict)
  # Return the data
  # return(pred_no_na)
  return(varpredict)
}
#' Function to Calculate Loss from the above predictions
#'
#' @param symbol - symbol to work with from quantmod. Must be in quotations to work
#' @param start_dt - start date of the data to build the forecast on 
#' @param end_dt - end date of the data to build the forecast on  
#' @param nfcst - number of data points to use in the forecast
#' @param model - model to use. Defaults to 1
#' @param level - level of significance. Defaults to 1%
#' @param G - argument for the k parameter in the 4th model (adaptive). Default is 5
#'
#' @return - loss using absolute value
#' @export - a plot of the data
#'
#' @examples
loss_calc_uv = function(symbol, start_dt, end_dt, nfcst, model = 1, level = 0.01, G = 5){
  # Pull in the data
  raw_data = data_pull(symbol, start_date = start_dt, end_date = end_dt)
  # Forecast based on the data
  fcst = na.omit(rolling_predictions(raw_data, nfcst = nfcst, model = model, level = level, G = G))*(-1)
  # Extract actuals
  act = tail(raw_data, n = nfcst)[,2]
  # Join the two together and rename
  join = merge(fcst,act,all=TRUE)
  colnames(join) <- c("Fcst_VaR", "Act_Return")
  # print(join)
  # Calculate the losses
  loss = abs(sum(ifelse(act > fcst, level, (-1)*(1-level))))
  # Plot the data
  plot = plot.xts(join, col = c("red", "black"), lty = c(2,1), main = "Log Return from the SPY vs. Fcst. VaR",grid.col = NA, legend.loc = "bottomleft")
  return(list(loss, plot, act, fcst))
}
#' This is a function which creates a data frame for the response and explanatory variables that we'll feed into the diffusion index
#'
#' @param symbol_list - a list of symbols recognizable by the 
#' @param resp_var - the response variable we'd like to forecast; default is SPY
#' @param compl_case - defaults to true...only includes complete cases in the data
#' @param adj_close - use adjusted closing prices for the explanatory variables? default is 1 for YES
#' @param resp_adj_close - use adjusted closing prices for the explanatory variables? default is 1 for YES
#' @param start_date - starting data to use
#' @param end_date - ending date of the data
#' @param lag_pred - do we lag the predictions? It is STRONGLY recommended that this is 0
#'
#' @return - a data frame which can be fed into the SWfore function
#' @export
#'
#' @examples - diff_index_df(c("XLF", "XLE", "PSCT", "XLV", "VPU", "XLP", "IGF", "XWEB", "PPTY"))
diff_index_df = function(symbol_list, resp_var = "SPY", compl_case = 1, adj_close = 1, resp_adj_close = 1, start_date = "1900-01-01", end_date = Sys.Date(), lag_pred = 1){
  # Pull in response variable
  response_pull = getSymbols(resp_var, auto.assign = FALSE, from = start_date, to = end_date)
  # Get adjusted closing price
  if (resp_adj_close == TRUE){
    diff_df = Ad(response_pull)
  } else {
    diff_df = Cl(response_pull)
  }
  # Loop through the symbols and join in data
  for (i in 1:length(symbol_list)){
    # Pull closing price
    expl_pull = getSymbols(symbol_list[i], auto.assign = FALSE, from = start_date, to = end_date)
    # Extract closing price - 4th element
    if (adj_close == TRUE){
      expl_cl = Ad(expl_pull)
    } else {
      expl_cl = Cl(expl_pull)
    }
    # New code for 4.16.2020 - lag the explanatory variables
    if (lag_pred == TRUE){
      # Lag the explanatory variables by 1
      lag_exp = lag(expl_cl, 1)
      # Append the first lag to the data frame
      diff_df = merge(diff_df, lag_exp, join = "left", fill = NA)
    } else{
      # Return the data frame without lags
      diff_df = merge(diff_df, expl_cl, join = "left", fill = NA)
    }
  }
  if (lag_pred == TRUE){
    # Chop off the first row
    diff_df = diff_df[-1,]
  }
  else {
    print("PLEASE NOTE - the explanatory variables in this DF are NOT lagged. Be careful to avoid look-ahead bias!")
  }
  # Return complete cases only 
  if (compl_case == TRUE){
    diff_df_out = diff_df[complete.cases(diff_df), ]
  } else{
    diff_df_out = diff_df
  }
  
  return(diff_df_out)
}
#' Converts a diff_df into a data frame with approximate percentage changes diff(log(diff_df))
#'
#' @param diff_df - output of the diff_index_df function with complete cases
#'
#' @return - retuns the differenced data
#' @export
#'
#' @examples - pc_diff_index(test_compl) 
pc_diff_index = function(diff_df){
  # Difference the log of the data
  pc_diff_index = diff(log(diff_df))
  # Remove the first row
  pc_diff_index_out = pc_diff_index[-1,]
  return(pc_diff_index_out)
}
#' Below is the modified diffusion index code.
#'
#' @param y - response variable
#' @param x - predictor variables
#' @param orig - forecast origin
#' @param m - number of diffusion indexes used
#' @param tau - VaR level to use; must be between 0 and 1
#' @param end - specifies an alternate ending value
#' @param print_mdl - print the model summary and the MSE
#'
#' @return - returns a list of variables for use in the diffusion index
#' @export
#'
#' @examples
mod_di = function (y, x, orig, m, tau, end = NULL, print_mdl = 0) 
{
  # Converts the response variables into a matrix
  if (!is.matrix(x)) 
      x = as.matrix(x)
  # nT is number of t time-steps
  nT = dim(x)[1]
  # Add a line to establish the number of data points used in the test.
  if (is.null(end) != TRUE){
    nT = end
  }
  # k is the number of diffusion indices used
  k = dim(x)[2]
  # Sanity checks to ensure that the origin isn't past the number of time points
  if (orig > nT) 
      orig = nT
  # Makes sure that there aren't more predictors than there variables in the dataset
  if (m > k) 
      m = k
  # Makes sure there are at least some variables
  if (m < 1) 
      m = 1
  # Subdivides the dataframe
  x1 = x[1:orig, ]
  # Calculates means of each row
  me = apply(x1, 2, mean)
  # Calculates standard deviations of each column
  se = sqrt(apply(x1, 2, var))
  # Creates a matrix x1, which normalizes all the columns. 
  # This may be an issue since it assumes that the distribution is sufficiently described by the first two moments
  x1 = x
  for (i in 1:k) {
      x1[, i] = (x1[, i] - me[i])/se[i]
  }
  V1 = cov(x1[1:orig, ])
  # Performs an eigen decomposition
  m1 = eigen(V1)
  # Selects eigenvalues
  sdev = m1$values
  # Selects eigenvectors
  M = m1$vectors
  # Makes a smaller matrix
  M1 = M[, 1:m]
  # This is the diffusion index model - [orig x p]*[p x m] = [orig x m]
  Dindex = x1 %*% M1
  # Cut down both the response and predictors to be a reasonable size
  y1 = y[1:orig]
  DF = Dindex[1:orig, ]
  # Apply the linear model - HERE is the key.
  # mm = lm(y1 ~ DF) - old function
  mm = rq(y1 ~ DF, tau = tau)
  # Print the data
  if (print_mdl == 1){
    print(summary(mm))
  }
  # Puts coefficients in a matrix
  coef = matrix(mm$coefficients, (m + 1), 1)
  # Initializes yhat variables and MSE
  yhat = NULL
  MSE = NULL
  if (orig < nT) {
    # Creates a nfcst by (m+1) matrix
    newx = cbind(rep(1, (nT - orig)), Dindex[(orig + 1):nT, 
        ])
    # [nfcstx(m+1)]*[(m+1)x1] = [nfcstx1]
    yhat = newx %*% coef
    # Calculates errors
    err = y[(orig + 1):nT] - yhat
    MSE = mean(err^2)
    if (print_mdl == 1){
      cat("MSE of out-of-sample forecasts: ", MSE, "\n")
    }
  }
  SWfore <- list(coef = coef, yhat = yhat, MSE = MSE, loadings = M1, 
      DFindex = Dindex)
}
#' Below is the modified diffusion index code to include lagged variables.
#'
#' @param y - response variable
#' @param x - predictor variables
#' @param orig - forecast origin
#' @param m - number of diffusion indexes used
#' @param tau - VaR level to use; must be between 0 and 1
#' @param ar_tf - AR transformation type. (1 - no transformation,
#' 2 - absolute value, 3 - asymmetric slope)
#' @param p - number of AR lags to include. Default is one.
#' @param print_mdl - option to print the model summary to make sure everytning is ok. 0 is default.
#' @param model - model type (1 - SAV, 2 - AS, 3 - GARCH, 4 - ADAPTIVE) 
#'
#' @return - returns a list of variables for use in the diffusion index
#' @export
#'
#' @examples
mod_di_wl = function (y, x, orig, m, tau, ar_tf = 1, p = 1, print_mdl = 0, model = 1, end = NULL) 
{
  # Converts the response variables into a matrix
  if (!is.matrix(x)) 
      x = as.matrix(x)
  # nT is number of t time-steps
  nT = dim(x)[1]
  # Add a line to establish the number of data points used in the test.
  if (is.null(end) != TRUE){
    nT = end
  }
  # k is the number of diffusion indices used
  k = dim(x)[2]
  # Sanity checks to ensure that the origin isn't past the number of time points
  if (orig > nT) 
      orig = nT
  # Makes sure that there aren't more predictors than there variables in the dataset
  if (m > k) 
      m = k
  # Makes sure there are at least some variables
  if (m < 1) 
      m = 1
  # Subdivides the dataframe
  x1 = x[1:orig, ]
  # Calculates means of each row
  me = apply(x1, 2, mean)
  # Calculates standard deviations of each column
  se = sqrt(apply(x1, 2, var))
  # Creates a matrix x1, which normalizes all the columns. 
  # This may be an issue since it assumes that the distribution is sufficiently described by the first two moments
  x1 = x
  for (i in 1:k) {
      x1[, i] = (x1[, i] - me[i])/se[i]
  }
  V1 = cov(x1[1:orig, ])
  # Performs an eigen decomposition
  m1 = eigen(V1)
  # Selects eigenvalues
  sdev = m1$values
  # Selects eigenvectors
  M = m1$vectors
  # Makes a smaller matrix
  M1 = M[, 1:m]
  # This is the diffusion index model - [orig x p]*[p x m] = [orig x m]
  Dindex = x1 %*% M1
  # Cut down both the response and predictors to be a reasonable size
  y1 = y[1:orig]
  DF = Dindex[1:orig, ]
  # Copy the data frame
  DF_wl = Dindex
  # Lag the y-variable
  for (i in 1:p){
    # Create a lagged variable
    lag_var = lag(y, i)
    # Append the first lag to the data frame
    DF_wl = cbind(DF_wl,lag_var)
  }
  # Identify the right columns
  l_ar = ncol(DF_wl)
  f_ar = l_ar - p + 1
  # Keep the last columns kept to the side
  all_lag = DF_wl[,(f_ar:l_ar)]
  # Cut off the first row to avoid NA's
  DF_trim = DF_wl[1:orig,]
  # Rename the columns
  # Here's the new function with an untransformed AR(p) lag
  if (ar_tf == 1){
    # Incorporate everything in to an input data frame
    df_in = cbind(y1[-(1:p)], DF_trim[-(1:p),])
    # Rename the columns
    # Initialize a character vector
    nvec = c(rep(0, 1+m+p))
    # Populate the vector - first value is the response
    nvec[1] <- names(y)
    # Next are the diffusion indices
    for (i in 1:m){
      nvec[i+1] = paste0("Diff_Index_", i)
    }
    # Next are the lagged variables
    for (i in 1:p){
      nvec[i+1+m] = paste0("Lag_", i)
    }
    # Assign the names
    names(df_in) <- nvec
    # Run the model
    mm = rq(df_in[,1] ~ df_in[,-1], tau = tau)
  }
  # Here's the new function with an SAV AR(p) lag
  if (ar_tf == 2){
    # Incorporate everything in to an input data frame
    df_in = cbind(y1[-(1:p)], DF_trim[-(1:p),-(f_ar:l_ar)], abs(DF_trim[-(1:p),(f_ar:l_ar)]))
    # Rename the columns
    # Initialize a character vector
    nvec = c(rep(0, 1+m+p))
    # Populate the vector - first value is the response
    nvec[1] <- names(y)
    # Next are the diffusion indices
    for (i in 1:m){
      nvec[i+1] = paste0("Diff_Index_", i)
    }
    # Next are the lagged variables
    for (i in 1:p){
      nvec[i+1+m] = paste0("Lag_", i)
    }
    # Assign the names. Note that this is a matrix
    names(df_in) <- nvec
    # Run the model
    mm = rq(df_in[,1] ~ df_in[,-1], tau = tau)
  }
  # Here's the new function with an asymmetric slope for the AR(1) lag
  # Indicator; 0 if percent change is negative, 1 if it's positive
  # indi = ifelse(DF_trim[,ar] < 0, 0, 1)
  if (ar_tf == 3){
    # Create a matrix of indicators
    indi_mat = matrix(0, nrow(DF_wl), p)
    # Generalize the above code
    for (i in 1:p){
      # Populate the indicator
      indi_mat[,i] = ifelse(DF_wl[,f_ar + i - 1] < 0, 0, 1)
    }
  }
  # Fitting the regression
  if (ar_tf == 3){
    # Incorporate everything in to an input data frame
    df_in = cbind(y1[-(1:p)], DF_trim[-(1:p),-(f_ar:l_ar)], DF_trim[-(1:p),(f_ar:l_ar)], indi_mat[((p+1):orig),])
    # Rename the columns
    # Initialize a character vector
    nvec = c(rep(0, 1+m+2*p))
    # Populate the vector - first value is the response
    nvec[1] <- names(y)
    # Next are the diffusion indices
    for (i in 1:m){
      nvec[i+1] = paste0("Diff_Index_", i)
    }
    # Next are the lagged variables
    for (i in 1:p){
      nvec[i+1+m] = paste0("Lag_", i)
    }
    # Last are the positive indicator variables
    for (i in 1:p){
      nvec[i+1+m+p] = paste0("Pos_Val_for_Lag_", i)
    }
    # Assign the names. Note that this is a matrix
    names(df_in) <- nvec
    # Run the model
    mm = rq(df_in[,1] ~ df_in[,-1], tau = tau)
    # mm = rq(y1[-(1:p)] ~ DF_trim[-(1:p),-(f_ar:l_ar)] + DF_trim[-(1:p),(f_ar:l_ar)] + indi_mat[((p+1):orig),], tau = tau)
    # Add a different line to account for the indicator variable
    # intercept + m + 2*nlag to account for the number of indicator variables
    coef = matrix(mm$coefficients, (1 + m + 2*p), 1)
  }
  if (print_mdl == 1){
    print(summary(mm))
  }
  # Puts coefficients in a matrix - added the AR terms
  # coef = matrix(mm$coefficients, (m + 1), 1)
  if (ar_tf != 3){
    coef = matrix(mm$coefficients, (1 + m + p), 1)
  }
  # Initializes yhat variables and MSE
  yhat = NULL
  loss = NULL
  if (orig < nT) {
    # Creates a nfcst by (m+2) matrix
    # Add on the lagged variables
    newx = cbind(rep(1, (nT - orig)), Dindex[(orig + 1):nT, ], all_lag[(orig+1):nT,])
    # Incorporate lagged variables
    if (ar_tf == 3){
      newx = cbind(rep(1, (nT - orig)), Dindex[(orig + 1):nT, ], all_lag[(orig+1):nT,], indi_mat[(orig+1):nT,])
    }
    # [nfcstx(m+1)]*[(m+1)x1] = [nfcstx1]
    yhat = newx %*% coef
    # Calculates errors
    loss = abs(sum(ifelse(y[(orig + 1):nT] > yhat, tau, (-1)*(1-tau))))
    # Modifying this part to only print this if specified
    if (print_mdl == 1){
      cat("Losses of out-of-sample forecasts: ", loss, "\n")
    }
  }
  SWfore <- list(coef = coef, yhat = yhat, loss = loss, loadings = M1, 
      DFindex = Dindex, name_vector = nvec)
}
# Decide on the optimal number of vectors.
# (y, x, orig, m, tau) 
#' Function that calculates loss over a given period of time for the diffusion index model
#'
#' @param y - response variables
#' @param x - explanatory variable
#' @param orig - forecast origin
#' @param end - forecasting ending. Note: as the function is currently written on 2/24, this option doesn't do anything.
#' @param m - number of diffusion indices to use
#' @param tau - VaR level
#' @param mod_di - use the modified DI?
#'
#' @return - returns a list of the loss sum and the loss vector
#' @export
#'
#' @examples - loss_calc(pc_df[,1], pc_df[,-1], 757, 1027, 1, 0.01)
loss_calc = function(y, x, orig, m, tau, mod_di = 0, ar_tf = 1, p = 1, print_mdl = 0, model = 1, end = NULL){
  # Extract y_hat values
  if (mod_di == 0){
    di = mod_di(y=y,x=x,orig=orig,m=m, tau=tau, end = end, print_mdl = print_mdl)
  }
  else {
    di = mod_di_wl(y=y,x=x,orig=orig,m=m, tau=tau, ar_tf = ar_tf, p = p, print_mdl = print_mdl, model = model, end = end)
  }
  # mod_di_wl = function (y, x, orig, m, tau, ar_tf = 1, p = 1, print_mdl = 0, model = 1)
  yhat = di$yhat[1:(end-orig)]
  # Calculate the loss
  # Initialize loss vector
  lvec = rep(0,(end-orig))
  # Take the difference
  for (i in 1:(end-orig)){
    # Calculate an indicator variable
    ind = ifelse(y[orig+i] < yhat[i], 1,0)
    # Use indicator in function below
    lvec[i] = (tau - ind)*(y[orig+i] - yhat[i])
  }
  # Add up the losses - change to look at sum of losses. Won't change decision criterion
  sumloss = sum(lvec)
  # sumloss = sum(lvec)/length(lvec)
  return(list(sumloss,lvec))
}
#' Function that selects the optimal number of predictors
#'
#' @param y - response vector
#' @param x - predictor variables
#' @param orig - forecast origin
#' @param end - ending of validation set
#' @param tau - VaR in question
#' @param low_m - low value of m to consider
#' @param high_m - high value of m to consider
#'
#' @return - returns the optimal value of m
#' @export
#'
#' @examples - opt_m(pc_df[,1], pc_df[,-1], 757, 1027, 0.01, low_m =1, high_m  = 5)
opt_m = function(y, x, orig, end = NULL, tau, low_m = 1, high_m, mod_di = 0, ar_tf = 1, p = 1, print_mdl = 0, model = 1, rowname = NULL){
  # Initialize a loss vector
  loss_vec = rep(0,high_m-low_m + 1)
  # Initialize an m vector
  m_vec = seq(low_m, high_m, by = 1)
  # Loop through and populate the loss vector
  for (i in 1:length(loss_vec)){
    loss_vec[i] = quiet(loss_calc(y=y,x=x,orig=orig,end=end, m = m_vec[i], tau = tau, mod_di = mod_di, ar_tf = ar_tf, p = p, print_mdl = print_mdl, model = model))[[1]]
  }
  # Find the minimizer
  opt_m = which.min(loss_vec)
  opt_p = NA
  # Combine into a data frame
  df = as.data.frame(cbind(opt_m, opt_p))
  names(df) <- c("Optimal m", "Optimal p")
  # Assign a rowname
  if (is.null(rowname) == TRUE){
    # Write the row names
    rownames(df) <- c("MV CAViaR")
  }
  else {
    rownames(df) <- rowname
  }
  # Return the loss_vector and the minimzer
  return(list(opt_m, loss_vec, df))
}
#' Function that selects the optimal number of lags
#'
#' @param y - response vector
#' @param x - predictor variables
#' @param orig - forecast origin
#' @param end - ending of validation set
#' @param tau - VaR in question
#' @param low_m - low value of m to consider
#' @param high_m - high value of m to consider
#'
#' @return - returns the optimal value of m
#' @export
#'
#' @examples - opt_mp(y = pc_df[,1], x = pc_df[,-1], orig = 757, end = 1007, tau = 0.01, low_m =1, high_m  = 5, low_p = 1, high_p = 10, ar_tf = 2, mod_di = 1)
opt_mp = function(y, x, orig, end = NULL, tau, low_m = 1, high_m, low_p = 1, high_p, mod_di = 0, ar_tf = 1, print_mdl = 0, model = 1, print_mp = 0, rowname = NULL){
  # Initialize a loss matrix
  loss_mat = matrix(0, high_p-low_p + 1,high_m-low_m + 1)
  # Initialize a p vector
  p_vec = seq(low_p, high_p, by = 1)
  # Loop through and populate the loss vector
  for (i in 1:nrow(loss_mat)){
    loss_mat[i,] = opt_m(y = y, x = x, orig = orig, end = end, tau = tau, low_m = low_m, high_m  = high_m, p = i, mod_di = mod_di, ar_tf = ar_tf, print_mdl = print_mdl, model = model)[[2]]
  }
  # Find the minimizer
  opt_p = which(loss_mat == min(loss_mat), arr.ind = TRUE)[1,1]
  opt_m = which(loss_mat == min(loss_mat), arr.ind = TRUE)[1,2]
  # Print the optimal p and optimal m
  df = as.data.frame(cbind(opt_m, opt_p))
  names(df) <- c("Optimal m", "Optimal p")
  # Assign a rowname
  if (is.null(rowname) == TRUE){
    if (ar_tf == 1){
      # Write the row names
      rownames(df) <- c("MV CAViaR + AR")
    } else if (ar_tf == 2){
      # Write the row names
      rownames(df) <- c("MV CAViaR + SAV")
    } else if (ar_tf == 3){
      # Write the row names
      rownames(df) <- c("MV CAViaR + AS")
    } else {
      rownames(df) <- c("Unknown Model")
    }
  }
  else {
    rownames(df) <- rowname
  }
  # Print the df if the option is turned on
  if (print_mp == 1){
    print(df)
  }
  # Return the loss_vector and the minimzer
  return(list(opt_m, opt_p, loss_mat, df))
}
#' A function that combines optimal values of m and p into a final table
#'
#' @param m1 - the data frame from the "MV CAViaR" run
#' @param m2 - the data frame from the "MV CAViaR + AR" run
#' @param m3 - the data frame from the "MV CAViaR + SAV" run
#' @param m4 - the data frame from the "MV CAViaR + AS" run
#'
#' @return - a nicely formatted table
#' @export
#'
#' @examples - pretty_pm(opt_pred_nl[[3]], opt_pm_m1[[4]], opt_pm_m2[[4]], opt_pm_m3[[4]])
pretty_pm = function(m1, m2, m3, m4){
  # Merge the individual data frames
  pm_pretty_df = rbind(m1, m2, m3, m4)
  # Format nicely
  pm_pretty_df %>% kable(caption = "Optimal Number of Diffusion Indices (m) and Lags (p) for Different Models", digits = 0) %>% kable_styling("striped", full_width = F) %>% kable_styling() %>% footnote(general = "The MV CAViaR model doesn't have an optimal value for p because there are no AR lags in the model"
  )
  
}
#' Here is a function that runs the univariate CAViaR model 4 times
#'
#' @param df - the percent change data frame to consider
#' @param nfcst - number of forecasts to run
#' @param tau - the VaR level to consider
#' @param no_run - specifies if any models should not be run
#'
#' @return - a list of the 4 univariate model forecasts
#' @export
#'
#' @examples - aceg = gen_uv_test(pc_df, 1, 0.05, no_run = c(1,1,0,1))
gen_uv_test = function(df, nfcst, tau, no_run = c(0,0,0,0)){
  # model type (1 - SAV, 2 - AS, 3 - GARCH, 4 - ADAPTIVE) 
  # Initialize a list  
  out_list = list()
  # Run the four models - model 1; SAV
  if (no_run[1] == 0){
    uvcav_1 = rolling_predictions(df[,1], range_data = (1:length(df[,1])), nfcst = nfcst, model = 1, G = 10, col = 1, level = tau)
  }
  # Add a filler if there's no entry
  else {
    uvcav_1 = 0
  }
  # Model 2 - AS
  if (no_run[2] == 0){
    uvcav_2 = rolling_predictions(df[,1], range_data = (1:length(df[,1])), nfcst = nfcst, model = 2, G = 10, col = 1, level = tau)
  }
  else {
    uvcav_2 = 0
  }
  # Model 3 - GARCH
  if (no_run[3] == 0){
    uvcav_3 = rolling_predictions(df[,1], range_data = (1:length(df[,1])), nfcst = nfcst, model = 3, G = 10, col = 1, level = tau)
  }
  else {
    uvcav_3 = 0
  }
  # Model 4 - Adaptive
  if (no_run[4] == 0){
    uvcav_4 = rolling_predictions(df[,1], range_data = (1:length(df[,1])), nfcst = nfcst, model = 4, G = 10, col = 1, level = tau)
  }
  else {
    uvcav_4 = 0
  }
  # Export the data as a list
  return(list(uvcav_1, uvcav_2, uvcav_3, uvcav_4))
}
#' Function to plot the data which we generate in previous functions
#'
#' @param plot_matrix - matrix with the data to plot
#' @param norm_value - what to subtact from the data to make it on a percentage change basis. Default is 100.
#'
#' @return 
#' @export - a plot of the data by diffusion index number
#'
#' @examples = plt_data(plot_mtx[[1]]), abc = plt_data(plot_mat, tau = 0.01)
plt_data = function(plot_matrix, tau, resp_var, ntest){
  # Establish a maximum and minimum value
  max_val = max(plot_matrix[,1:ncol(plot_matrix)])
  min_val = min(plot_matrix[,1:ncol(plot_matrix)])
  # Calculate inital and ending time value
  start = index(plot_matrix)[1]
  end = index(plot_matrix)[nrow(plot_matrix)]
  ind_vals = index(plot_matrix) - start
  # Create an initial plot and add lines
    for (i in 1:ncol(plot_matrix)){
      if (i == 1){
        # 4/2/2020 - fixing the index
        plot.ts(ind_vals,plot_matrix[,i], type = "l", xlab = paste("Days Since", as.Date(start)), ylab = "Percent Change in PG", ylim = c(min_val,max_val), lwd = 1, main = paste("Predicting", resp_var, "Returns from", as.Date(start), "to", as.Date(end)), sub = paste("The VaR Level is ", 100*tau, "%", "; There are ", ntest, " Trading Days Plotted Above", sep = ""))
        # plot.ts(index(plot_matrix), plot_matrix[,i], type = "l", xlab = "Trading Days", ylab = "Percent Change in PG", ylim = c(min_val,max_val), lwd = 1, main = "Predicting PG Returns Over Last 250 Trading Days in 2008", sub = paste("The VaR Level is ", 100*tau, "%", sep = ""))
    } else if(i %in% seq(2,8,1)) {
        lines(ind_vals,plot_matrix[,i], col = i-1, lty = 2)
    } else {
        lines(ind_vals,plot_matrix[,i], col = i-1, lty = 2, lwd = 2)
    }
    }
  # Define a sequence for plotting
  plot_seq = seq(1, ncol(plot_matrix))
  legend("topleft", legend = c(colnames(plot_matrix)), col = plot_seq, lty = c(1, rep(2, 7), rep(3, ifelse(ncol(plot_matrix)-8 <= 0, 0, ncol(plot_matrix)-8))), lwd = c(1, rep(1, 7), rep(2, ifelse(ncol(plot_matrix)-8 <= 0, 0, ncol(plot_matrix)-8))))
  # Add a line for 0
  # abline(h = 0, col = "black", lty = 2)
}
#' A function to calculate losses based on the test sample
#'
#' @param true_vec - the true vector of returns
#' @param pred_vec - the predicted vector from the model runs
#' @param tau - VaR level. Must match what the model used
#'
#' @return - total losses and the entire loss vector
#' @export
#'
#' @examples
loss_test = function(true_vec, pred_vec, tau){
  # Initialize a loss vector
  lvec = rep(0, length(true_vec))
  # Initialize a break vector to see when VaR is broken
  bvec = rep(0, length(true_vec))
  for (i in 1:length(true_vec)){
    # Calculate an indicator variable
    bvec[i] = ifelse(true_vec[i] < pred_vec[i], 1,0)
    # Use indicator in function below
    lvec[i] = (tau - bvec[i])*(true_vec[i] - pred_vec[i])
  }
  # Add up the losses
  # sumloss = sum(lvec)/length(lvec)
  sumloss = sum(lvec)
  # Add up the VaR breakage
  varbreak = sum(bvec)/length(bvec)
  return(list(sumloss,lvec, varbreak, bvec))
}
#' A function to calculate losses based on the plot matrix
#'
#' @param data_mat - a matrix of forecasted VaR values, with the true value in the first column
#' @param tau - VaR level. Must match what the model used
#'
#' @return - a list of four items. 
#' 1 = a vector of the losses of all models. 
#' 2 = a vector showing the percentage of VaR breaks by model
#' 3 = the loss matrix
#' 4 = the break matrix
#' @export
#'
#' @examples
gen_loss_test = function(data_mat, tau){
  # Initialize loss and break matrices
  lmat = bmat = matrix(0, nrow = nrow(data_mat), ncol = ncol(data_mat)-1)
  # bvec = rep(0, length(true_vec))
  # Populate the matrices
  for (i in 1:nrow(lmat)){
    for (j in 1:(ncol(lmat))){
      # Calculate an indicator variable
      bmat[i,j] = ifelse(data_mat[i,1] < data_mat[i,j+1], 1,0)
      # Use indicator in function below
      lmat[i,j] = (tau - bmat[i,j])*(data_mat[i,1] - data_mat[i,j+1])
    }    
  }
  # Add up the losses
  sumloss = colSums(lmat)
  # Add up the VaR breakage
  varbreak = colSums(bmat)/nrow(bmat)
  return(list(sumloss, varbreak, lmat, bmat))
}
#' A function to make a nice comparison of losses
#'
#' @param data_mat - input data matrix used in the calculation of losses
#' @param loss_list - a list of the losses calculated from the CAViaR function
#' @param tau - the risk level used
#' @param ntest - the number of test points
#'
#' @return
#' @export - returns a nicely formatted table
#'
#' @examples - pretty_tables(plot_mat, l_list, tau = 0.01)
pretty_tables = function(data_mat, loss_list, tau, ntest){
  # Combine into a data frame
  df = as.data.frame(rbind(loss_list[[1]], loss_list[[2]]))
  # Calculate inital and ending time value
  start = index(data_mat)[1]
  end = index(data_mat)[nrow(data_mat)]
  # Add row/column names
  colnames(df) <- colnames(data_mat[,-1])
  rownames(df) <- c("Losses", "VaR Breaks (%)")
  # Convert to a table
  df %>% kable(caption = paste("Comparison of VaR Methods for a ", tau*100, "% VaR", sep = ""), digits = 3) %>% kable_styling("striped", full_width = F) %>% kable_styling() %>% footnote(general = paste("Calculated using", ntest, "trading days from", as.Date(start), "to", as.Date(end)))
}
#' A dressed up version of the export function
#'
#' @param var_file - file to export
#' @param path - filepath
#' @param filename - name of the file, ending with .CSV
#'
#' @return
#' @export - exported CSV file
#'
#' @examples - exp_func(var_file = var_1pc_2016_usetf[[1]], path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/", filename = "TEST.csv")
exp_func = function(var_file, path, filename){
  # Write a zoo
  write.zoo(var_file, paste0(path, filename), quote = FALSE, sep = ",")
}
# exp_func(var_file = var_1pc_2016_usetf[[1]], path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/", filename = "TEST.csv")

Big Simulation Function

#' This is the "master" function where we'll evaluate the importance of the VaR model over several time periods
#'
#' @param symbol_list - a list of symbols to feed into the model 
#' @param resp_var - the response variable
#' @param compl_case - should the model require complete cases? Default value is 1.
#' @param adj_close - use adjusted close price for the predictors? Default value is 1.
#' @param resp_adj_close - use adjusted close price for the response? Default value is 1.
#' @param start_date - start date to pull data from
#' @param end_date - end date to pull data from
#' @param nval - number of validation points to use
#' @param ntest - number of test points to use
#' @param tau - VaR level to use
#' @param low_m - low number of predictors to test
#' @param high_m  - low number of predictors to test
#' @param uv_list - a list of a pre-run univariate model. If a data frame is not provided, the lengthy uv model will run 
#' @param no_run - things not to run in the model
#' @param low_p - low value for number of lags
#' @param high_p - high value for number of lags
#' @param na_interp - should the function interpolate NA's
#' @param print_mdl - print the model summaries?
#' @param print_mp - print the optimal values for p and m
#' @param lag_pred - do you want to lag the m predictors (default is 1; strongly recommended)
#' @param rowname - what to name the rows of the nice p and m matrix
#' @param export_csv - do you want to export a CSV? Default is 1.
#' @param path - path to export the CSV
#' @param filename - what to name the CSV
#'
#' @return - a list of the plot matrix, a plot, a list with losses, and a table
#' @export - a plot and a table
#'
#' @examples - cav_simul(c("DIS", "GE", "IBM", "MMM", "XOM"), resp_var = "PG", start_date = "2004-01-01", end_date = "2008-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 5, tau = 0.01, uv_list = uv_cav_list)
cav_simul = function(symbol_list, resp_var, compl_case = 1, adj_close = 1, resp_adj_close = 1, start_date = "1900-01-01", end_date = Sys.Date(), nval, ntest, tau, low_m = 1, high_m, low_p = 1, high_p, uv_list = NULL, no_run = c(0,0,0,0), na_interp = TRUE, print_mdl = 0, print_mp = 0, lag_pred = 1, rowname = NULL, export_csv = 1, path, filename){
  # Select data parameters, pull the data, and percent change the data
  df = diff_index_df(symbol_list = symbol_list, resp_var = resp_var, compl_case = compl_case, adj_close = adj_close, resp_adj_close = resp_adj_close, start_date = start_date, end_date = end_date, lag_pred = lag_pred)
  # Take the percent change of the data
  pc_df = pc_diff_index(df)
  # Extract the legnth of the data frame
  nr = test_end = nrow(pc_df)
  # Calculate the start of the val period, the end of the val period, and the beginning and end of test period
  test_orig = test_end - ntest
  val_end = test_orig
  val_orig = test_orig - nval
  # Test for the optimal number of parameters
  opt_pred_nl = opt_m(y = pc_df[,1], x = pc_df[,-1], orig = val_orig, end = val_end, tau = tau, low_m = low_m, high_m = high_m, rowname = rowname)
  opt_pred_art1 = opt_mp(y = pc_df[,1], x = pc_df[,-1], orig = val_orig, end = val_end, tau = tau, low_m = low_m, high_m = high_m, low_p = low_p, high_p = high_p,mod_di = 1, ar_tf = 1, print_mdl = print_mdl, print_mp = print_mp, rowname = rowname)
  opt_pred_art2 = opt_mp(y = pc_df[,1], x = pc_df[,-1], orig = val_orig, end = val_end, tau = tau, low_m = low_m, high_m = high_m, low_p = low_p, high_p = high_p,mod_di = 1, ar_tf = 2, print_mdl = print_mdl, print_mp = print_mp, rowname = rowname)
  opt_pred_art3 = opt_mp(y = pc_df[,1], x = pc_df[,-1], orig = val_orig, end = val_end, tau = tau, low_m = low_m, high_m = high_m, low_p = low_p, high_p = high_p, mod_di = 1, ar_tf = 3, print_mdl = print_mdl, print_mp = print_mp, rowname = rowname)
  # gen_uv_test(pc_df, 1, 0.05, no_run = c(1,1,0,1))
  # Use the above forecasts to input into the above
  mv_fcst = mod_di(pc_df[,1], pc_df[,-1], orig = test_orig, m = opt_pred_nl[[1]], tau = tau, print_mdl = print_mdl)
  mv_fcst_art1 = mod_di_wl(pc_df[,1], pc_df[,-1], orig = test_orig, m = opt_pred_art1[[1]], p = opt_pred_art1[[2]], tau = tau, ar_tf = 1, print_mdl = print_mdl)
  mv_fcst_art2 = mod_di_wl(pc_df[,1], pc_df[,-1], orig = test_orig, m = opt_pred_art2[[1]], p = opt_pred_art2[[2]], tau = tau, ar_tf = 2, print_mdl = print_mdl)
  mv_fcst_art3 = mod_di_wl(pc_df[,1], pc_df[,-1], orig = test_orig, m = opt_pred_art3[[1]], p = opt_pred_art3[[2]], tau = tau, ar_tf = 3, print_mdl = print_mdl)
  # Calculate the number of predictions
  if (is.null(uv_list) == TRUE){
    # Print a warning
    print("WARNING: Not supplying an input data frame will require this function to run for a significant amount of time (1hr+)")
    # Call the function
    # gen_uv_test = function(df, nfcst, tau, no_run = c(0,0,0,0)){
    # print(head(pc_df))
    uv_list = gen_uv_test(df = pc_df, nfcst = ntest, tau = tau, no_run = no_run)
    # Add to a data frame
    # Incorporate the rolling predictions function results here
  plot_mat = cbind(pc_df[(test_orig+1):nrow(pc_df),1], mv_fcst$yhat[1:ntest], mv_fcst_art1$yhat[1:ntest], mv_fcst_art2$yhat[1:ntest], mv_fcst_art3$yhat[1:ntest], uv_list[[1]][(test_orig+1):test_end]*(-1), uv_list[[2]][(test_orig+1):test_end]*(-1), uv_list[[3]][(test_orig+1):test_end]*(-1), uv_list[[4]][(test_orig+1):test_end]*(-1))
  } else {
    # Assign the columns of the data frame
    # head(var_5pc_2010_usetf[[1]][,6:9])
    # model type (1 - SAV, 2 - AS, 3 - GARCH, 4 - ADAPTIVE) 
    # test_df = head(var_5pc_2010_usetf[[1]][,6:9])
    # test_df$SAV
    # test_df$`Abs. Slope`
    # test_df$`Ind. GARCH`
    # test_df$Adaptive
    plot_mat = cbind(pc_df[(test_orig+1):nrow(pc_df),1], mv_fcst$yhat[1:ntest], mv_fcst_art1$yhat[1:ntest], mv_fcst_art2$yhat[1:ntest], mv_fcst_art3$yhat[1:ntest], uv_list$SAV, uv_list$`Abs. Slope`, uv_list$`Ind. GARCH`, uv_list$Adaptive)
  }
  # Count the NAs and print a warning
  print(paste("NOTE: There are ", sum(is.na(plot_mat)), " NA(s) in the dataset", sep = ""))
  # Linearly interpolate the NAs
  if (na_interp == TRUE){
    # Assign the plot matrix to a new value
    plot_mat_na <- plot_mat
    # Print a warning
    print("WARNING: There were missing values in the plot matrix.")
    # Interpolate the NA's
    for (i in 1:ncol(plot_mat_na)){
      # Interpolate the data
      plot_mat[,i] <- na.approx(plot_mat_na[,i])
    }
  }
  # model type (1 - SAV, 2 - AS, 3 - GARCH, 4 - ADAPTIVE)
  # Add descriptive titles onto the plot_mat
  colnames(plot_mat) <- c(resp_var, "MV CAViaR", "MV CAViaR + AR", "MV CAViaR + SAV", "MV CAViaR + AS", "SAV", "Abs. Slope", "Ind. GARCH", "Adaptive")
  # colnames(plot_mat) <- c("SPY", "MV CAViaR", "MV CAViaR + AR", "MV CAViaR + SAV", "MV CAViaR + AS", "SAV", "Abs. Slope", "Ind. GARCH", "Adaptive")
  # Plot everything
  plot = plt_data(plot_mat, tau = tau, resp_var = resp_var, ntest = ntest)
  # Calculate losses
  l_list = gen_loss_test(plot_mat, tau = tau)
  # Put into tables
  tables = pretty_tables(plot_mat, l_list, tau = tau, ntest = ntest)
  # Run the function for optimal p and m
  pm_table = pretty_pm(opt_pred_nl[[3]], opt_pred_art1[[4]], opt_pred_art2[[4]], opt_pred_art3[[4]])
  # Export the matrix
  if (export_csv == 1){
    exp_func(var_file = plot_mat, path, filename)
  }
  # Print the tables and the plot
  print(plot)
  print(tables)
  print(pm_table)
  return(list(plot_mat, plot, l_list, tables, plot_mat_na, pm_table))
}
#' A function to input the VaR files, plot them and generate tables
#'
#' @param file_path - file path to use
#' @param filename - name of the file
#' @param tau - quantile to use
#' @param resp_var - response variable to use in the plot
#' @param ntest - number of test points
#' @param cn_input - column name inputs
#'
#' @return - a list of the xts file, the plot, the loss list, and tables
#' @export - a plot and tables
#'
#' @examples - test = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/","var_1pc_2008_us_etf.csv", 0.01)
var_input_disp = function(file_path, filename, tau, resp_var = "SPY", ntest = 250, cn_input = c("SPY", "MV CAViaR", "MV CAViaR + AR", "MV CAViaR + SAV", "MV CAViaR + AS", "SAV", "Abs. Slope", "Ind. GARCH", "Adaptive")){
# var_input_disp = function(file_path, filename, tau, resp_var = "SPY", ntest = 250, cn_input = c("SPY", "MV CAViaR", "MV CAViaR + AR", "MV CAViaR + SAV", "MV CAViaR + AS", "SAV", "Abs. Slope", "Ind. GARCH", "Adaptive")){
  # Import data
  plot_mat = read.csv(paste0(file_path,filename), sep = ",", header = T, stringsAsFactors = FALSE)
  # Fix date format
  plot_mat$Index = as.Date(plot_mat$Index)
  # Convert to an xts
  plot_mat = xts(plot_mat[,-1], order.by = plot_mat[,1])
  # Fix column names
  colnames(plot_mat) <- cn_input
  # Plot everything
  plt_data(plot_mat, tau = tau, resp_var = resp_var, ntest = ntest)
  # plot = plt_data(plot_mat, tau = tau, resp_var = resp_var, ntest = ntest)
  # Calculate losses
  l_list = gen_loss_test(plot_mat, tau = tau)
  # Put into tables
  df = as.data.frame(rbind(l_list[[1]], l_list[[2]]))
  # Calculate inital and ending time value
  start = index(plot_mat)[1]
  end = index(plot_mat)[nrow(plot_mat)]
  # Add row/column names
  colnames(df) <- colnames(plot_mat[,-1])
  rownames(df) <- c("Losses", "VaR Breaks (%)")
  # Convert to a table
  print(df, digits = 3)
  # print(formattable(df, digits = 3))
  # df %>% kable(caption = paste("Comparison of VaR Methods for a ", tau*100, "% VaR", sep = ""), digits = 3) %>% kable_styling("striped", full_width = F) %>% kable_styling() %>% footnote(general = paste("Calculated using", ntest, "trading days from", as.Date(start), "to", as.Date(end)))
  # pm_table = pretty_tables(plot_mat, l_list, tau = tau, ntest = ntest)
  # Print the tables and the plot
  # print(plot)
  # print(tables)
  # print(pm_table)
  # Return the xts, the plot, the loss list, and the tables
  return(list(plot_mat))
  # return(list(plot_mat, plot, l_list, tables))
}

2008 Ending

U.S. ETFs

# return(list(plot_mat, plot, l_list, tables))
# Call the above function
v1_2008_usetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/","var_1pc_2008_us_etf.csv", 0.01)

# pretty_tables(v1_2008_usetf[[1]], v1_2008_usetf[[3]], tau = 0.01, ntest = 250)
v5_2008_usetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/","var_5pc_2008_us_etf.csv", 0.05)

v10_2008_usetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/","var_10pc_2008_us_etf.csv", 0.10)

# head(v10_2008_usetf[[1]])
# v10_2008_usetf

The results for the U.S. ETFs clearly show that the univariate model outperforms the multivariate model during the great recession.

# 1%, 5%, 10% VaR - 2008 - 1st set of predictors
# var_1pc_2008_us_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE"), resp_var = "SPY", start_date = "2004-01-01", end_date = "2008-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 9, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/", filename = "var_1pc_2008_us_etf.csv", uv_list = var_1pc_2008_usetf[[1]])
# var_5pc_2008_us_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE"), resp_var = "SPY", start_date = "2004-01-01", end_date = "2008-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 9, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/", filename = "var_5pc_2008_us_etf.csv", uv_list = var_5pc_2008_usetf[[1]])
# var_10pc_2008_us_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE"), resp_var = "SPY", start_date = "2004-01-01", end_date = "2008-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 9, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/", filename = "var_10pc_2008_us_etf.csv", uv_list = var_10pc_2008_usetf[[1]])

Global ETFs

# Call the above function
v1_2008_globetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/","var_1pc_2008_glob_etf.csv", 0.01)

v5_2008_globetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/","var_5pc_2008_glob_etf.csv", 0.05)

v10_2008_globetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/","var_10pc_2008_glob_etf.csv", 0.10)

While the model with the global ETFs as predictors performs better than the model with U.S. ETFs, the univariate CAViaR model outperforms the multivariate model.

# 1%, 5%, 10% VaR - 2008 - 2nd set of predictors
# var_1pc_2008_glob_etf = cav_simul(c("JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC"), resp_var = "SPY", start_date = "2004-01-01", end_date = "2008-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 10, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/", filename = "var_1pc_2008_glob_etf.csv", uv_list = var_1pc_2008_usetf[[1]])
# var_5pc_2008_glob_etf = cav_simul(c("JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC"), resp_var = "SPY", start_date = "2004-01-01", end_date = "2008-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 10, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/", filename = "var_5pc_2008_glob_etf.csv", uv_list = var_5pc_2008_usetf[[1]])
# var_10pc_2008_glob_etf = cav_simul(c("JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC"), resp_var = "SPY", start_date = "2004-01-01", end_date = "2008-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 10, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/", filename = "var_10pc_2008_glob_etf.csv", uv_list = var_10pc_2008_usetf[[1]])

Commodity ETFs

# 1%, 5%, 10% VaR - 2008 - 3rd set of predictors
# var_1pc_2008_comm_etf = cav_simul(c("DBA", "DBC", "DBE", "DBB"), resp_var = "SPY", start_date = "2004-01-01", end_date = "2008-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_comm_ETF_runs/", filename = "var_1pc_2008_comm_etf.csv", uv_list = var_1pc_2008_usetf[[1]])
# var_5pc_2008_comm_etf = cav_simul(c("DBA", "DBC", "DBE", "DBB"), resp_var = "SPY", start_date = "2004-01-01", end_date = "2008-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_comm_ETF_runs/", filename = "var_5pc_2008_comm_etf.csv", uv_list = var_5pc_2008_usetf[[1]])
# var_10pc_2008_comm_etf = cav_simul(c("DBA", "DBC", "DBE", "DBB"), resp_var = "SPY", start_date = "2004-01-01", end_date = "2008-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_comm_ETF_runs/", filename = "var_10pc_2008_comm_etf.csv", uv_list = var_10pc_2008_usetf[[1]])

Bond ETFs

# Call the above function
v1_2008_bondetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/","var_1pc_2008_bond_etf.csv", 0.01)

v5_2008_bondetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/","var_5pc_2008_bond_etf.csv", 0.05)

v10_2008_bondetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/","var_10pc_2008_bond_etf.csv", 0.10)

As with the previous two runs, the univariate model outperforms the multivariate model.

# iShares 1-3 Year Treasury Bond Fund (SHY)
# iShares 7-10 Year Treasury Bond Fund (IEF)
# iShares 20+ Year Treasury Bond Fund (TLT)
# iShares iBoxx $ Investment Grade Corporate Bond ETF (LQD)
# 1%, 5%, 10% VaR - 2008 - 4th set of predictors
# var_1pc_2008_bond_etf = cav_simul(c("SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2004-01-01", end_date = "2008-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/", filename = "var_1pc_2008_bond_etf.csv", uv_list = var_1pc_2008_usetf[[1]])
# var_5pc_2008_bond_etf = cav_simul(c("SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2004-01-01", end_date = "2008-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/", filename = "var_5pc_2008_bond_etf.csv", uv_list = var_5pc_2008_usetf[[1]])
# var_10pc_2008_bond_etf = cav_simul(c("SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2004-01-01", end_date = "2008-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/", filename = "var_10pc_2008_bond_etf.csv", uv_list = var_10pc_2008_usetf[[1]])

All ETFs

# Call the above function
v1_2008_alletf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/","var_1pc_2008_all_etf.csv", 0.01)

v5_2008_alletf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/","var_5pc_2008_all_etf.csv", 0.05)

v10_2008_alletf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/","var_10pc_2008_all_etf.csv", 0.10)

While the inclusion of more explanatory variables seems to help the forecast, the univariate model outperforms the multivariate model.

# 1%, 5%, 10% VaR - 2008 - 5th set of predictors
# var_1pc_2008_all_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE", "JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC", "SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2004-01-01", end_date = "2008-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 23, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/", filename = "var_1pc_2008_all_etf.csv", uv_list = var_1pc_2008_usetf[[1]])
# var_5pc_2008_all_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE", "JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC", "SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2004-01-01", end_date = "2008-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 23, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/", filename = "var_5pc_2008_all_etf.csv", uv_list = var_5pc_2008_usetf[[1]])
# var_10pc_2008_all_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE", "JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC", "SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2004-01-01", end_date = "2008-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 23, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/", filename = "var_10pc_2008_all_etf.csv", uv_list = var_10pc_2008_usetf[[1]])

2010 Ending

U.S. ETFs

# Call the above function
v1_2010_usetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/","var_1pc_2010_us_etf.csv", 0.01)

v5_2010_usetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/","var_5pc_2010_us_etf.csv", 0.05)

v10_2010_usetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/","var_10pc_2010_us_etf.csv", 0.10)

The results are much better for the multivariate model here during a more benign period.

# 1%, 5%, 10% VaR - 2010 - 1st set of predictors
# var_1pc_2010_us_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE"), resp_var = "SPY", start_date = "2006-01-01", end_date = "2010-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 9, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/", filename = "var_1pc_2010_us_etf.csv", uv_list = var_1pc_2010_usetf[[1]])
# var_5pc_2010_us_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE"), resp_var = "SPY", start_date = "2006-01-01", end_date = "2010-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 9, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/", filename = "var_5pc_2010_us_etf.csv", uv_list = var_5pc_2010_usetf[[1]])
# var_10pc_2010_us_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE"), resp_var = "SPY", start_date = "2006-01-01", end_date = "2010-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 9, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/", filename = "var_10pc_2010_us_etf.csv", uv_list = var_10pc_2010_usetf[[1]])

Global ETFs

# Call the above function
v1_2010_globetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/","var_1pc_2010_glob_etf.csv", 0.01)

v5_2010_globetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/","var_5pc_2010_glob_etf.csv", 0.05)

v10_2010_globetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/","var_10pc_2010_glob_etf.csv", 0.10)

As with the U.S. ETFs, the results are better.

# 1%, 5%, 10% VaR - 2010 - 2nd set of predictors
# var_1pc_2010_glob_etf = cav_simul(c("JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC"), resp_var = "SPY", start_date = "2006-01-01", end_date = "2010-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 10, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/", filename = "var_1pc_2010_glob_etf.csv", uv_list = var_1pc_2010_usetf[[1]])
# var_5pc_2010_glob_etf = cav_simul(c("JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC"), resp_var = "SPY", start_date = "2006-01-01", end_date = "2010-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 10, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/", filename = "var_5pc_2010_glob_etf.csv", uv_list = var_5pc_2010_usetf[[1]])
# var_10pc_2010_glob_etf = cav_simul(c("JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC"), resp_var = "SPY", start_date = "2006-01-01", end_date = "2010-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 10, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/", filename = "var_10pc_2010_glob_etf.csv", uv_list = var_10pc_2010_usetf[[1]])

Commodity ETFs

# 1%, 5%, 10% VaR - 2010 - 3rd set of predictors
# var_1pc_2010_comm_etf = cav_simul(c("DBA", "DBC", "DBE", "DBB"), resp_var = "SPY", start_date = "2006-01-01", end_date = "2010-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_comm_ETF_runs/", filename = "var_1pc_2010_comm_etf.csv", uv_list = var_1pc_2010_usetf[[1]])
# var_5pc_2010_comm_etf = cav_simul(c("DBA", "DBC", "DBE", "DBB"), resp_var = "SPY", start_date = "2006-01-01", end_date = "2010-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_comm_ETF_runs/", filename = "var_5pc_2010_comm_etf.csv", uv_list = var_5pc_2010_usetf[[1]])
# var_10pc_2010_comm_etf = cav_simul(c("DBA", "DBC", "DBE", "DBB"), resp_var = "SPY", start_date = "2006-01-01", end_date = "2010-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_comm_ETF_runs/", filename = "var_10pc_2010_comm_etf.csv", uv_list = var_10pc_2010_usetf[[1]])

Bond ETFs

# Call the above function
v1_2010_bondetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/","var_1pc_2010_bond_etf.csv", 0.01)

v5_2010_bondetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/","var_5pc_2010_bond_etf.csv", 0.05)

v10_2010_bondetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/","var_10pc_2010_bond_etf.csv", 0.10)

As with the previous two runs, the results from the bond ETFs are better than those from 2008.

# iShares 1-3 Year Treasury Bond Fund (SHY)
# iShares 7-10 Year Treasury Bond Fund (IEF)
# iShares 20+ Year Treasury Bond Fund (TLT)
# iShares iBoxx $ Investment Grade Corporate Bond ETF (LQD)
# 1%, 5%, 10% VaR - 2010 - 4th set of predictors
# var_1pc_2010_bond_etf = cav_simul(c("SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2006-01-01", end_date = "2010-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/", filename = "var_1pc_2010_bond_etf.csv", uv_list = var_1pc_2010_usetf[[1]])
# var_5pc_2010_bond_etf = cav_simul(c("SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2006-01-01", end_date = "2010-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/", filename = "var_5pc_2010_bond_etf.csv", uv_list = var_5pc_2010_usetf[[1]])
# var_10pc_2010_bond_etf = cav_simul(c("SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2006-01-01", end_date = "2010-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/", filename = "var_10pc_2010_bond_etf.csv", uv_list = var_10pc_2010_usetf[[1]])

All ETFs

# Call the above function
v1_2010_alletf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/","var_1pc_2010_all_etf.csv", 0.01)

v5_2010_alletf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/","var_5pc_2010_all_etf.csv", 0.05)

v10_2010_alletf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/","var_10pc_2010_all_etf.csv", 0.10)

The inclusion of all predictors reveals similar results for the multivariate models as the previous forecasts; the results are generally in-line the univariate CAViaR model.

# 1%, 5%, 10% VaR - 2010 - 5th set of predictors
# var_1pc_2010_all_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE", "JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC", "SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2006-01-01", end_date = "2010-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 23, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/", filename = "var_1pc_2010_all_etf.csv", uv_list = var_1pc_2010_usetf[[1]])
# var_5pc_2010_all_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE", "JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC", "SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2006-01-01", end_date = "2010-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 23, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/", filename = "var_5pc_2010_all_etf.csv", uv_list = var_5pc_2010_usetf[[1]])
# var_10pc_2010_all_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE", "JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC", "SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2006-01-01", end_date = "2010-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 23, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/", filename = "var_10pc_2010_all_etf.csv", uv_list = var_10pc_2010_usetf[[1]])

2014 Ending

U.S. ETFs

# Call the above function
v1_2014_usetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/","var_1pc_2014_us_etf.csv", 0.01)

v5_2014_usetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/","var_5pc_2014_us_etf.csv", 0.05)

v10_2014_usetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/","var_10pc_2014_us_etf.csv", 0.10)

As with the results in 2014, the results from the U.S. ETFs shows a similar quality of predictions.

# 1%, 5%, 10% VaR - 2014 - 1st set of predictors
# var_1pc_2014_us_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE"), resp_var = "SPY", start_date = "2010-01-01", end_date = "2014-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 9, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/", filename = "var_1pc_2014_us_etf.csv", uv_list = var_1pc_2014_usetf[[1]])
# var_5pc_2014_us_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE"), resp_var = "SPY", start_date = "2010-01-01", end_date = "2014-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 9, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/", filename = "var_5pc_2014_us_etf.csv", uv_list = var_5pc_2014_usetf[[1]])
# var_10pc_2014_us_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE"), resp_var = "SPY", start_date = "2010-01-01", end_date = "2014-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 9, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/", filename = "var_10pc_2014_us_etf.csv", uv_list = var_10pc_2014_usetf[[1]])

Global ETFs

# Call the above function
v1_2014_globetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/","var_1pc_2014_glob_etf.csv", 0.01)

v5_2014_globetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/","var_5pc_2014_glob_etf.csv", 0.05)

v10_2014_globetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/","var_10pc_2014_glob_etf.csv", 0.10)

The results show that the multivariate predictions are of similar quality to the predictions from the univariate model.

# 1%, 5%, 10% VaR - 2014 - 2nd set of predictors
# var_1pc_2014_glob_etf = cav_simul(c("JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC"), resp_var = "SPY", start_date = "2010-01-01", end_date = "2014-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 10, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/", filename = "var_1pc_2014_glob_etf.csv", uv_list = var_1pc_2014_usetf[[1]])
# var_5pc_2014_glob_etf = cav_simul(c("JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC"), resp_var = "SPY", start_date = "2010-01-01", end_date = "2014-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 10, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/", filename = "var_5pc_2014_glob_etf.csv", uv_list = var_5pc_2014_usetf[[1]])
# var_10pc_2014_glob_etf = cav_simul(c("JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC"), resp_var = "SPY", start_date = "2010-01-01", end_date = "2014-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 10, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/", filename = "var_10pc_2014_glob_etf.csv", uv_list = var_10pc_2014_usetf[[1]])

Commodity ETFs

# 1%, 5%, 10% VaR - 2014 - 3rd set of predictors
# var_1pc_2014_comm_etf = cav_simul(c("DBA", "DBC", "DBE", "DBB"), resp_var = "SPY", start_date = "2010-01-01", end_date = "2014-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_comm_ETF_runs/", filename = "var_1pc_2014_comm_etf.csv", uv_list = var_1pc_2014_usetf[[1]])
# var_5pc_2014_comm_etf = cav_simul(c("DBA", "DBC", "DBE", "DBB"), resp_var = "SPY", start_date = "2010-01-01", end_date = "2014-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_comm_ETF_runs/", filename = "var_5pc_2014_comm_etf.csv", uv_list = var_5pc_2014_usetf[[1]])
# var_10pc_2014_comm_etf = cav_simul(c("DBA", "DBC", "DBE", "DBB"), resp_var = "SPY", start_date = "2010-01-01", end_date = "2014-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_comm_ETF_runs/", filename = "var_10pc_2014_comm_etf.csv", uv_list = var_10pc_2014_usetf[[1]])

Bond ETFs

# Call the above function
v1_2014_bondetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/","var_1pc_2014_bond_etf.csv", 0.01)

v5_2014_bondetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/","var_5pc_2014_bond_etf.csv", 0.05)

v10_2014_bondetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/","var_10pc_2014_bond_etf.csv", 0.10)

As with the other two sets of regressors, the results here show that the multivariate predictions are of similar quality to the predictions from the univariate model.

# iShares 1-3 Year Treasury Bond Fund (SHY)
# iShares 7-10 Year Treasury Bond Fund (IEF)
# iShares 20+ Year Treasury Bond Fund (TLT)
# iShares iBoxx $ Investment Grade Corporate Bond ETF (LQD)
# 1%, 5%, 10% VaR - 2014 - 4th set of predictors
# var_1pc_2014_bond_etf = cav_simul(c("SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2010-01-01", end_date = "2014-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/", filename = "var_1pc_2014_bond_etf.csv", uv_list = var_1pc_2014_usetf[[1]])
# var_5pc_2014_bond_etf = cav_simul(c("SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2010-01-01", end_date = "2014-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/", filename = "var_5pc_2014_bond_etf.csv", uv_list = var_5pc_2014_usetf[[1]])
# var_10pc_2014_bond_etf = cav_simul(c("SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2010-01-01", end_date = "2014-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/", filename = "var_10pc_2014_bond_etf.csv", uv_list = var_10pc_2014_usetf[[1]])

All ETFs

# Call the above function
v1_2014_alletf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/","var_1pc_2014_all_etf.csv", 0.01)

v5_2014_alletf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/","var_5pc_2014_all_etf.csv", 0.05)

v10_2014_alletf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/","var_10pc_2014_all_etf.csv", 0.10)

Including all the ETFs as regressors provides a multivariate forecast with similar accuracy to that of the univariate model.

# 1%, 5%, 10% VaR - 2014 - 5th set of predictors
# var_1pc_2014_all_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE", "JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC", "SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2010-01-01", end_date = "2014-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 23, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/", filename = "var_1pc_2014_all_etf.csv", uv_list = var_1pc_2014_usetf[[1]])
# var_5pc_2014_all_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE", "JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC", "SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2010-01-01", end_date = "2014-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 23, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/", filename = "var_5pc_2014_all_etf.csv", uv_list = var_5pc_2014_usetf[[1]])
# var_10pc_2014_all_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE", "JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC", "SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2010-01-01", end_date = "2014-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 23, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/", filename = "var_10pc_2014_all_etf.csv", uv_list = var_10pc_2014_usetf[[1]])

2016 Ending

U.S. ETFs

# Call the above function
v1_2016_usetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/","var_1pc_2016_us_etf.csv", 0.01)

v5_2016_usetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/","var_5pc_2016_us_etf.csv", 0.05)

v10_2016_usetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/","var_10pc_2016_us_etf.csv", 0.10)

As with the forecast in 2010 and 2014, including the U.S. ETFs as predictors in the multivariate model gives similar results to that of the univariate model.

# 1%, 5%, 10% VaR - 2016 - 1st set of predictors
# var_1pc_2016_us_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE"), resp_var = "SPY", start_date = "2012-01-01", end_date = "2016-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 9, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/", filename = "var_1pc_2016_us_etf.csv", uv_list = var_1pc_2016_usetf[[1]])
# var_5pc_2016_us_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE"), resp_var = "SPY", start_date = "2012-01-01", end_date = "2016-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 9, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/", filename = "var_5pc_2016_us_etf.csv", uv_list = var_5pc_2016_usetf[[1]])
# var_10pc_2016_us_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE"), resp_var = "SPY", start_date = "2012-01-01", end_date = "2016-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 9, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/", filename = "var_10pc_2016_us_etf.csv", uv_list = var_10pc_2016_usetf[[1]])

Global ETFs

# Call the above function
v1_2016_globetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/","var_1pc_2016_glob_etf.csv", 0.01)

v5_2016_globetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/","var_5pc_2016_glob_etf.csv", 0.05)

v10_2016_globetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/","var_10pc_2016_glob_etf.csv", 0.10)

The global ETFs as predictors provide solid results as well.

# 1%, 5%, 10% VaR - 2016 - 2nd set of predictors
# var_1pc_2016_glob_etf = cav_simul(c("JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC"), resp_var = "SPY", start_date = "2012-01-01", end_date = "2016-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 10, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/", filename = "var_1pc_2016_glob_etf.csv", uv_list = var_1pc_2016_usetf[[1]])
# var_5pc_2016_glob_etf = cav_simul(c("JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC"), resp_var = "SPY", start_date = "2012-01-01", end_date = "2016-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 10, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/", filename = "var_5pc_2016_glob_etf.csv", uv_list = var_5pc_2016_usetf[[1]])
# var_10pc_2016_glob_etf = cav_simul(c("JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC"), resp_var = "SPY", start_date = "2012-01-01", end_date = "2016-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 10, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/", filename = "var_10pc_2016_glob_etf.csv", uv_list = var_10pc_2016_usetf[[1]])

Commodity ETFs

# 1%, 5%, 10% VaR - 2016 - 3rd set of predictors
# var_1pc_2016_comm_etf = cav_simul(c("DBA", "DBC", "DBE", "DBB"), resp_var = "SPY", start_date = "2012-01-01", end_date = "2016-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_comm_ETF_runs/", filename = "var_1pc_2016_comm_etf.csv", uv_list = var_1pc_2016_usetf[[1]])
# var_5pc_2016_comm_etf = cav_simul(c("DBA", "DBC", "DBE", "DBB"), resp_var = "SPY", start_date = "2012-01-01", end_date = "2016-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_comm_ETF_runs/", filename = "var_5pc_2016_comm_etf.csv", uv_list = var_5pc_2016_usetf[[1]])
# var_10pc_2016_comm_etf = cav_simul(c("DBA", "DBC", "DBE", "DBB"), resp_var = "SPY", start_date = "2012-01-01", end_date = "2016-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_comm_ETF_runs/", filename = "var_10pc_2016_comm_etf.csv", uv_list = var_10pc_2016_usetf[[1]])

Bond ETFs

# Call the above function
v1_2016_bondetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/","var_1pc_2016_bond_etf.csv", 0.01)

v5_2016_bondetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/","var_5pc_2016_bond_etf.csv", 0.05)

v10_2016_bondetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/","var_10pc_2016_bond_etf.csv", 0.10)

As with the U.S. and Global ETFs, the bond ETFs provide good results.

# iShares 1-3 Year Treasury Bond Fund (SHY)
# iShares 7-10 Year Treasury Bond Fund (IEF)
# iShares 20+ Year Treasury Bond Fund (TLT)
# iShares iBoxx $ Investment Grade Corporate Bond ETF (LQD)
# 1%, 5%, 10% VaR - 2016 - 4th set of predictors
# var_1pc_2016_bond_etf = cav_simul(c("SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2012-01-01", end_date = "2016-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/", filename = "var_1pc_2016_bond_etf.csv", uv_list = var_1pc_2016_usetf[[1]])
# var_5pc_2016_bond_etf = cav_simul(c("SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2012-01-01", end_date = "2016-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/", filename = "var_5pc_2016_bond_etf.csv", uv_list = var_5pc_2016_usetf[[1]])
# var_10pc_2016_bond_etf = cav_simul(c("SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2012-01-01", end_date = "2016-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/", filename = "var_10pc_2016_bond_etf.csv", uv_list = var_10pc_2016_usetf[[1]])

All ETFs

# Call the above function
v1_2016_alletf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/","var_1pc_2016_all_etf.csv", 0.01)

v5_2016_alletf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/","var_5pc_2016_all_etf.csv", 0.05)

v10_2016_alletf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/","var_10pc_2016_all_etf.csv", 0.10)

Including all ETFs as predictors yields good quality results for the 2016 test period.

# 1%, 5%, 10% VaR - 2016 - 5th set of predictors
# var_1pc_2016_all_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE", "JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC", "SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2012-01-01", end_date = "2016-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 23, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/", filename = "var_1pc_2016_all_etf.csv", uv_list = var_1pc_2016_usetf[[1]])
# var_5pc_2016_all_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE", "JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC", "SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2012-01-01", end_date = "2016-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 23, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/", filename = "var_5pc_2016_all_etf.csv", uv_list = var_5pc_2016_usetf[[1]])
# var_10pc_2016_all_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE", "JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC", "SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2012-01-01", end_date = "2016-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 23, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/", filename = "var_10pc_2016_all_etf.csv", uv_list = var_10pc_2016_usetf[[1]])

Conclusions and Future Work

The problem of how to predict a low quantile of a stock’s log return when the training sample is substantially different than the test scenario is an enormously difficult problem. Almost axiomatically, the distribution is nonstationary over time. How is it possible to predict the return of an index like the S&P500 during a period of market turmoil such as the great recession? While the CAViaR model performs comparatively well during times of stress, it performs about the same as the multivariate model during more benign economic periods.

This conclusion drawn from the above results might support the notion of combining the two models in some sort of a mixture model - aiming to use the basket of ETFs during good times, and use the CAViaR ARMA specification during bad times. The approach of using ETFs allows a prediction based on forward-looking expectations of fundamental factors. Indeed, ETFs are just baskets of individual stocks or bonds, and those securities are (in theory) based on rational expectations about future resources, market conditions, etc - the microfoundations of what drives our economy. The ARMA specification, while practically and statistically sound, is contradicted by economic theory and practice - the weak form of the efficient market hypothesis states that it is impossible to forecast future values of asset prices using past values. But perhaps this view is incomplete.

Any model that attempts to capture relationships in the real world will only work until an omitted variable is found. The elegance of the multivariate CAViaR model is that it provides insight into why a prediction is wrong; the change in the angle between resultant vectors is a sensible measurement of economic changepoints (CHANGE). However, errors in the world are costly, and it’s wishful thinking to say that explaining why the error occurred is sufficient.

As such, for future work it’s worth exploring the notion of weighting an ARMA-approach more heavily when predictions using fundamentals were too high, then not only would this after-the-fact recognition be achieves, but also a hierarchical model that captures fundamental relationships in the economy and potentially changes our understanding of asset prices in general - a synthesis between Keynes’ animal spirits during a time of severe crisis; where a model cannot explain shifts, and a more rational world that explains other periods. In addition to significant predictive power because of the switching between the two worlds, there’s also an elegant explanation; a way to explain changes in the usefulness of the underpinnings in the economy. Because of the flexibility of the model, it’s entirely possible that a whole gamut of variables could be tossed in and backtested to when “changepoints” occurred.

Additional future work involves developing theoretical guarantees on the parameters in the multivariate CAViaR model. One advantage of both the diffusion index model and the CAViaR model is that both have theorems about asymptotic normality and consistency [CONFIRM].

Code Appendix

knitr::opts_chunk$set(fig.width=12, fig.height=8, fig.path='Figs/',
                      echo=FALSE, warning=FALSE, message=FALSE, cache = TRUE)
# Read in relevant libraries
library(microbenchmark)
library(data.table)
library(quantmod)
library(ggplot2)
library(tseries)
library(zoo)
library(magrittr)
library(dplyr)
library(kableExtra)
library(formattable)
library(quantreg)
library(MTS)
library(plot3D)
library(citr)
library(formattable)

# Set up working directory
# setwd("~/Documents/GitHub/CaviaR")

# source('caviar_SM.R')
source('~/Documents/GitHub/CaviaR/caviar_SM.R')
# This code below is for use in the CAViaR sections.
# Here is code that I'll wrap some parts in to avoid superfluous output
quiet <- function(x) { 
  sink(tempfile()) 
  on.exit(sink()) 
  invisible(force(x)) 
} 
#' This is a function which pulls data for use in the CAViaR model
#'
#' @param symbol - symbol to pull
#' @param compl_case - defaults to true...only includes complete cases in the data
#' @param adj_close - use adjusted closing prices. Default is yes.
#' @param log_return - use log return? Default is yes.
#'
#' @return - a data frame which can be fed into later functions
#' @export
#'
#' @examples - data_pull("SPY")
data_pull = function(symbol, compl_case = 1, adj_close = 1, log_return = 1, start_date = "1900-01-01", end_date = Sys.Date()){
  # Pull in data from quantmod
  response_pull = getSymbols(symbol, auto.assign = FALSE, from = start_date, to = end_date)
  # Get adjusted closing price
  if (adj_close == TRUE){
    df = Ad(response_pull)
  } else {
    df = Cl(response_pull)
  }
  # Return complete cases only 
  if (compl_case == TRUE){
    df = df[complete.cases(df), ]
  } else{
    df = df
  }
  # Calculate log return of data
  if (log_return == TRUE){
    lr = log(df[,1]/shift(df[,1], 1, type = "lag"))
    # Combine data
    df_out = cbind(df, lr)
    # Rename the data 
    colnames(df_out) <- c(sym=symbol, paste0(symbol, "_log_return"))
  } else{
    df_out = df
  }
  # Return data
  return(df_out)
}


#' Pull the data and run the CAViaR function on it
#'
#' @param input_data - data to use in the function
#' @param range_data - range of the data to use
#'
#' @return - a list of values from the caviar function
#' @export
#'
#' @examples - caviar_pull(spy)
caviar_pull = function(input_data, range_data = (2:dim(input_data)[1])){
  # Run the caviar data
  caviar <- caviarOptim(input_data[range_data,2])
  return(caviar)
}

#' Function for producing rolling predictions
#' Model 1 = Symmetric Absolute Value, 2 = Asymmetric slope, 3 = Indirect GARCH, 4 = Adaptive
#'
#' @param input_data - input data from the previous function
#' @param range_data - range of the data to consider
#' @param nfcst - number of forecasts to make
#' @param model - model to use (integers 1 through 4). Defaults to 1. 
#' @param level - level of significance to use.
#' @param G - argument for the k parameter in the 4th model (adaptive). Default is 5
#'
#' @return - an xts object which contains rolling CAViaR predictions
#' @export
#'
#' @examples - rolling_predictions(spy, nfcst = 22)
rolling_predictions = function(input_data, range_data = (2:dim(input_data)[1]), nfcst = 250, model =1, level = 0.01, G = 5, col = 2){
  # Run the varpredict function
  varpredict <- rollapplyr(input_data[range_data,col], length(range_data) - nfcst, caviarOptim, model, level, predict = 1, k = G) %>% lag
  # Eliminate NAs
  # pred_no_na = na.omit(varpredict)
  # Return the data
  # return(pred_no_na)
  return(varpredict)
}

#' Function to Calculate Loss from the above predictions
#'
#' @param symbol - symbol to work with from quantmod. Must be in quotations to work
#' @param start_dt - start date of the data to build the forecast on 
#' @param end_dt - end date of the data to build the forecast on  
#' @param nfcst - number of data points to use in the forecast
#' @param model - model to use. Defaults to 1
#' @param level - level of significance. Defaults to 1%
#' @param G - argument for the k parameter in the 4th model (adaptive). Default is 5
#'
#' @return - loss using absolute value
#' @export - a plot of the data
#'
#' @examples
loss_calc_uv = function(symbol, start_dt, end_dt, nfcst, model = 1, level = 0.01, G = 5){
  # Pull in the data
  raw_data = data_pull(symbol, start_date = start_dt, end_date = end_dt)
  # Forecast based on the data
  fcst = na.omit(rolling_predictions(raw_data, nfcst = nfcst, model = model, level = level, G = G))*(-1)
  # Extract actuals
  act = tail(raw_data, n = nfcst)[,2]
  # Join the two together and rename
  join = merge(fcst,act,all=TRUE)
  colnames(join) <- c("Fcst_VaR", "Act_Return")
  # print(join)
  # Calculate the losses
  loss = abs(sum(ifelse(act > fcst, level, (-1)*(1-level))))
  # Plot the data
  plot = plot.xts(join, col = c("red", "black"), lty = c(2,1), main = "Log Return from the SPY vs. Fcst. VaR",grid.col = NA, legend.loc = "bottomleft")
  return(list(loss, plot, act, fcst))
}

#' This is a function which creates a data frame for the response and explanatory variables that we'll feed into the diffusion index
#'
#' @param symbol_list - a list of symbols recognizable by the 
#' @param resp_var - the response variable we'd like to forecast; default is SPY
#' @param compl_case - defaults to true...only includes complete cases in the data
#' @param adj_close - use adjusted closing prices for the explanatory variables? default is 1 for YES
#' @param resp_adj_close - use adjusted closing prices for the explanatory variables? default is 1 for YES
#' @param start_date - starting data to use
#' @param end_date - ending date of the data
#' @param lag_pred - do we lag the predictions? It is STRONGLY recommended that this is 0
#'
#' @return - a data frame which can be fed into the SWfore function
#' @export
#'
#' @examples - diff_index_df(c("XLF", "XLE", "PSCT", "XLV", "VPU", "XLP", "IGF", "XWEB", "PPTY"))
diff_index_df = function(symbol_list, resp_var = "SPY", compl_case = 1, adj_close = 1, resp_adj_close = 1, start_date = "1900-01-01", end_date = Sys.Date(), lag_pred = 1){
  # Pull in response variable
  response_pull = getSymbols(resp_var, auto.assign = FALSE, from = start_date, to = end_date)
  # Get adjusted closing price
  if (resp_adj_close == TRUE){
    diff_df = Ad(response_pull)
  } else {
    diff_df = Cl(response_pull)
  }
  # Loop through the symbols and join in data
  for (i in 1:length(symbol_list)){
    # Pull closing price
    expl_pull = getSymbols(symbol_list[i], auto.assign = FALSE, from = start_date, to = end_date)
    # Extract closing price - 4th element
    if (adj_close == TRUE){
      expl_cl = Ad(expl_pull)
    } else {
      expl_cl = Cl(expl_pull)
    }
    # New code for 4.16.2020 - lag the explanatory variables
    if (lag_pred == TRUE){
      # Lag the explanatory variables by 1
      lag_exp = lag(expl_cl, 1)
      # Append the first lag to the data frame
      diff_df = merge(diff_df, lag_exp, join = "left", fill = NA)
    } else{
      # Return the data frame without lags
      diff_df = merge(diff_df, expl_cl, join = "left", fill = NA)
    }
  }
  if (lag_pred == TRUE){
    # Chop off the first row
    diff_df = diff_df[-1,]
  }
  else {
    print("PLEASE NOTE - the explanatory variables in this DF are NOT lagged. Be careful to avoid look-ahead bias!")
  }
  # Return complete cases only 
  if (compl_case == TRUE){
    diff_df_out = diff_df[complete.cases(diff_df), ]
  } else{
    diff_df_out = diff_df
  }
  
  return(diff_df_out)
}

#' Converts a diff_df into a data frame with approximate percentage changes diff(log(diff_df))
#'
#' @param diff_df - output of the diff_index_df function with complete cases
#'
#' @return - retuns the differenced data
#' @export
#'
#' @examples - pc_diff_index(test_compl) 

pc_diff_index = function(diff_df){
  # Difference the log of the data
  pc_diff_index = diff(log(diff_df))
  # Remove the first row
  pc_diff_index_out = pc_diff_index[-1,]
  return(pc_diff_index_out)
}

#' Below is the modified diffusion index code.
#'
#' @param y - response variable
#' @param x - predictor variables
#' @param orig - forecast origin
#' @param m - number of diffusion indexes used
#' @param tau - VaR level to use; must be between 0 and 1
#' @param end - specifies an alternate ending value
#' @param print_mdl - print the model summary and the MSE
#'
#' @return - returns a list of variables for use in the diffusion index
#' @export
#'
#' @examples
mod_di = function (y, x, orig, m, tau, end = NULL, print_mdl = 0) 
{
  # Converts the response variables into a matrix
  if (!is.matrix(x)) 
      x = as.matrix(x)
  # nT is number of t time-steps
  nT = dim(x)[1]
  # Add a line to establish the number of data points used in the test.
  if (is.null(end) != TRUE){
    nT = end
  }
  # k is the number of diffusion indices used
  k = dim(x)[2]
  # Sanity checks to ensure that the origin isn't past the number of time points
  if (orig > nT) 
      orig = nT
  # Makes sure that there aren't more predictors than there variables in the dataset
  if (m > k) 
      m = k
  # Makes sure there are at least some variables
  if (m < 1) 
      m = 1
  # Subdivides the dataframe
  x1 = x[1:orig, ]
  # Calculates means of each row
  me = apply(x1, 2, mean)
  # Calculates standard deviations of each column
  se = sqrt(apply(x1, 2, var))
  # Creates a matrix x1, which normalizes all the columns. 
  # This may be an issue since it assumes that the distribution is sufficiently described by the first two moments
  x1 = x
  for (i in 1:k) {
      x1[, i] = (x1[, i] - me[i])/se[i]
  }
  V1 = cov(x1[1:orig, ])
  # Performs an eigen decomposition
  m1 = eigen(V1)
  # Selects eigenvalues
  sdev = m1$values
  # Selects eigenvectors
  M = m1$vectors
  # Makes a smaller matrix
  M1 = M[, 1:m]
  # This is the diffusion index model - [orig x p]*[p x m] = [orig x m]
  Dindex = x1 %*% M1
  # Cut down both the response and predictors to be a reasonable size
  y1 = y[1:orig]
  DF = Dindex[1:orig, ]
  # Apply the linear model - HERE is the key.
  # mm = lm(y1 ~ DF) - old function
  mm = rq(y1 ~ DF, tau = tau)
  # Print the data
  if (print_mdl == 1){
    print(summary(mm))
  }
  # Puts coefficients in a matrix
  coef = matrix(mm$coefficients, (m + 1), 1)
  # Initializes yhat variables and MSE
  yhat = NULL
  MSE = NULL
  if (orig < nT) {
    # Creates a nfcst by (m+1) matrix
    newx = cbind(rep(1, (nT - orig)), Dindex[(orig + 1):nT, 
        ])
    # [nfcstx(m+1)]*[(m+1)x1] = [nfcstx1]
    yhat = newx %*% coef
    # Calculates errors
    err = y[(orig + 1):nT] - yhat
    MSE = mean(err^2)
    if (print_mdl == 1){
      cat("MSE of out-of-sample forecasts: ", MSE, "\n")
    }
  }
  SWfore <- list(coef = coef, yhat = yhat, MSE = MSE, loadings = M1, 
      DFindex = Dindex)
}

#' Below is the modified diffusion index code to include lagged variables.
#'
#' @param y - response variable
#' @param x - predictor variables
#' @param orig - forecast origin
#' @param m - number of diffusion indexes used
#' @param tau - VaR level to use; must be between 0 and 1
#' @param ar_tf - AR transformation type. (1 - no transformation,
#' 2 - absolute value, 3 - asymmetric slope)
#' @param p - number of AR lags to include. Default is one.
#' @param print_mdl - option to print the model summary to make sure everytning is ok. 0 is default.
#' @param model - model type (1 - SAV, 2 - AS, 3 - GARCH, 4 - ADAPTIVE) 
#'
#' @return - returns a list of variables for use in the diffusion index
#' @export
#'
#' @examples
mod_di_wl = function (y, x, orig, m, tau, ar_tf = 1, p = 1, print_mdl = 0, model = 1, end = NULL) 
{
  # Converts the response variables into a matrix
  if (!is.matrix(x)) 
      x = as.matrix(x)
  # nT is number of t time-steps
  nT = dim(x)[1]
  # Add a line to establish the number of data points used in the test.
  if (is.null(end) != TRUE){
    nT = end
  }
  # k is the number of diffusion indices used
  k = dim(x)[2]
  # Sanity checks to ensure that the origin isn't past the number of time points
  if (orig > nT) 
      orig = nT
  # Makes sure that there aren't more predictors than there variables in the dataset
  if (m > k) 
      m = k
  # Makes sure there are at least some variables
  if (m < 1) 
      m = 1
  # Subdivides the dataframe
  x1 = x[1:orig, ]
  # Calculates means of each row
  me = apply(x1, 2, mean)
  # Calculates standard deviations of each column
  se = sqrt(apply(x1, 2, var))
  # Creates a matrix x1, which normalizes all the columns. 
  # This may be an issue since it assumes that the distribution is sufficiently described by the first two moments
  x1 = x
  for (i in 1:k) {
      x1[, i] = (x1[, i] - me[i])/se[i]
  }
  V1 = cov(x1[1:orig, ])
  # Performs an eigen decomposition
  m1 = eigen(V1)
  # Selects eigenvalues
  sdev = m1$values
  # Selects eigenvectors
  M = m1$vectors
  # Makes a smaller matrix
  M1 = M[, 1:m]
  # This is the diffusion index model - [orig x p]*[p x m] = [orig x m]
  Dindex = x1 %*% M1
  # Cut down both the response and predictors to be a reasonable size
  y1 = y[1:orig]
  DF = Dindex[1:orig, ]
  # Copy the data frame
  DF_wl = Dindex
  # Lag the y-variable
  for (i in 1:p){
    # Create a lagged variable
    lag_var = lag(y, i)
    # Append the first lag to the data frame
    DF_wl = cbind(DF_wl,lag_var)
  }
  # Identify the right columns
  l_ar = ncol(DF_wl)
  f_ar = l_ar - p + 1
  # Keep the last columns kept to the side
  all_lag = DF_wl[,(f_ar:l_ar)]
  # Cut off the first row to avoid NA's
  DF_trim = DF_wl[1:orig,]
  # Rename the columns
  # Here's the new function with an untransformed AR(p) lag
  if (ar_tf == 1){
    # Incorporate everything in to an input data frame
    df_in = cbind(y1[-(1:p)], DF_trim[-(1:p),])
    # Rename the columns
    # Initialize a character vector
    nvec = c(rep(0, 1+m+p))
    # Populate the vector - first value is the response
    nvec[1] <- names(y)
    # Next are the diffusion indices
    for (i in 1:m){
      nvec[i+1] = paste0("Diff_Index_", i)
    }
    # Next are the lagged variables
    for (i in 1:p){
      nvec[i+1+m] = paste0("Lag_", i)
    }
    # Assign the names
    names(df_in) <- nvec
    # Run the model
    mm = rq(df_in[,1] ~ df_in[,-1], tau = tau)
  }
  # Here's the new function with an SAV AR(p) lag
  if (ar_tf == 2){
    # Incorporate everything in to an input data frame
    df_in = cbind(y1[-(1:p)], DF_trim[-(1:p),-(f_ar:l_ar)], abs(DF_trim[-(1:p),(f_ar:l_ar)]))
    # Rename the columns
    # Initialize a character vector
    nvec = c(rep(0, 1+m+p))
    # Populate the vector - first value is the response
    nvec[1] <- names(y)
    # Next are the diffusion indices
    for (i in 1:m){
      nvec[i+1] = paste0("Diff_Index_", i)
    }
    # Next are the lagged variables
    for (i in 1:p){
      nvec[i+1+m] = paste0("Lag_", i)
    }
    # Assign the names. Note that this is a matrix
    names(df_in) <- nvec
    # Run the model
    mm = rq(df_in[,1] ~ df_in[,-1], tau = tau)
  }
  # Here's the new function with an asymmetric slope for the AR(1) lag
  # Indicator; 0 if percent change is negative, 1 if it's positive
  # indi = ifelse(DF_trim[,ar] < 0, 0, 1)
  if (ar_tf == 3){
    # Create a matrix of indicators
    indi_mat = matrix(0, nrow(DF_wl), p)
    # Generalize the above code
    for (i in 1:p){
      # Populate the indicator
      indi_mat[,i] = ifelse(DF_wl[,f_ar + i - 1] < 0, 0, 1)
    }
  }
  # Fitting the regression
  if (ar_tf == 3){
    # Incorporate everything in to an input data frame
    df_in = cbind(y1[-(1:p)], DF_trim[-(1:p),-(f_ar:l_ar)], DF_trim[-(1:p),(f_ar:l_ar)], indi_mat[((p+1):orig),])
    # Rename the columns
    # Initialize a character vector
    nvec = c(rep(0, 1+m+2*p))
    # Populate the vector - first value is the response
    nvec[1] <- names(y)
    # Next are the diffusion indices
    for (i in 1:m){
      nvec[i+1] = paste0("Diff_Index_", i)
    }
    # Next are the lagged variables
    for (i in 1:p){
      nvec[i+1+m] = paste0("Lag_", i)
    }
    # Last are the positive indicator variables
    for (i in 1:p){
      nvec[i+1+m+p] = paste0("Pos_Val_for_Lag_", i)
    }
    # Assign the names. Note that this is a matrix
    names(df_in) <- nvec
    # Run the model
    mm = rq(df_in[,1] ~ df_in[,-1], tau = tau)
    # mm = rq(y1[-(1:p)] ~ DF_trim[-(1:p),-(f_ar:l_ar)] + DF_trim[-(1:p),(f_ar:l_ar)] + indi_mat[((p+1):orig),], tau = tau)
    # Add a different line to account for the indicator variable
    # intercept + m + 2*nlag to account for the number of indicator variables
    coef = matrix(mm$coefficients, (1 + m + 2*p), 1)
  }
  if (print_mdl == 1){
    print(summary(mm))
  }
  # Puts coefficients in a matrix - added the AR terms
  # coef = matrix(mm$coefficients, (m + 1), 1)
  if (ar_tf != 3){
    coef = matrix(mm$coefficients, (1 + m + p), 1)
  }
  # Initializes yhat variables and MSE
  yhat = NULL
  loss = NULL
  if (orig < nT) {
    # Creates a nfcst by (m+2) matrix
    # Add on the lagged variables
    newx = cbind(rep(1, (nT - orig)), Dindex[(orig + 1):nT, ], all_lag[(orig+1):nT,])
    # Incorporate lagged variables
    if (ar_tf == 3){
      newx = cbind(rep(1, (nT - orig)), Dindex[(orig + 1):nT, ], all_lag[(orig+1):nT,], indi_mat[(orig+1):nT,])
    }
    # [nfcstx(m+1)]*[(m+1)x1] = [nfcstx1]
    yhat = newx %*% coef
    # Calculates errors
    loss = abs(sum(ifelse(y[(orig + 1):nT] > yhat, tau, (-1)*(1-tau))))
    # Modifying this part to only print this if specified
    if (print_mdl == 1){
      cat("Losses of out-of-sample forecasts: ", loss, "\n")
    }
  }
  SWfore <- list(coef = coef, yhat = yhat, loss = loss, loadings = M1, 
      DFindex = Dindex, name_vector = nvec)
}

# Decide on the optimal number of vectors.

# (y, x, orig, m, tau) 

#' Function that calculates loss over a given period of time for the diffusion index model
#'
#' @param y - response variables
#' @param x - explanatory variable
#' @param orig - forecast origin
#' @param end - forecasting ending. Note: as the function is currently written on 2/24, this option doesn't do anything.
#' @param m - number of diffusion indices to use
#' @param tau - VaR level
#' @param mod_di - use the modified DI?
#'
#' @return - returns a list of the loss sum and the loss vector
#' @export
#'
#' @examples - loss_calc(pc_df[,1], pc_df[,-1], 757, 1027, 1, 0.01)
loss_calc = function(y, x, orig, m, tau, mod_di = 0, ar_tf = 1, p = 1, print_mdl = 0, model = 1, end = NULL){
  # Extract y_hat values
  if (mod_di == 0){
    di = mod_di(y=y,x=x,orig=orig,m=m, tau=tau, end = end, print_mdl = print_mdl)
  }
  else {
    di = mod_di_wl(y=y,x=x,orig=orig,m=m, tau=tau, ar_tf = ar_tf, p = p, print_mdl = print_mdl, model = model, end = end)
  }
  # mod_di_wl = function (y, x, orig, m, tau, ar_tf = 1, p = 1, print_mdl = 0, model = 1)
  yhat = di$yhat[1:(end-orig)]
  # Calculate the loss
  # Initialize loss vector
  lvec = rep(0,(end-orig))
  # Take the difference
  for (i in 1:(end-orig)){
    # Calculate an indicator variable
    ind = ifelse(y[orig+i] < yhat[i], 1,0)
    # Use indicator in function below
    lvec[i] = (tau - ind)*(y[orig+i] - yhat[i])
  }
  # Add up the losses - change to look at sum of losses. Won't change decision criterion
  sumloss = sum(lvec)
  # sumloss = sum(lvec)/length(lvec)
  return(list(sumloss,lvec))
}


#' Function that selects the optimal number of predictors
#'
#' @param y - response vector
#' @param x - predictor variables
#' @param orig - forecast origin
#' @param end - ending of validation set
#' @param tau - VaR in question
#' @param low_m - low value of m to consider
#' @param high_m - high value of m to consider
#'
#' @return - returns the optimal value of m
#' @export
#'
#' @examples - opt_m(pc_df[,1], pc_df[,-1], 757, 1027, 0.01, low_m =1, high_m  = 5)
opt_m = function(y, x, orig, end = NULL, tau, low_m = 1, high_m, mod_di = 0, ar_tf = 1, p = 1, print_mdl = 0, model = 1, rowname = NULL){
  # Initialize a loss vector
  loss_vec = rep(0,high_m-low_m + 1)
  # Initialize an m vector
  m_vec = seq(low_m, high_m, by = 1)
  # Loop through and populate the loss vector
  for (i in 1:length(loss_vec)){
    loss_vec[i] = quiet(loss_calc(y=y,x=x,orig=orig,end=end, m = m_vec[i], tau = tau, mod_di = mod_di, ar_tf = ar_tf, p = p, print_mdl = print_mdl, model = model))[[1]]
  }
  # Find the minimizer
  opt_m = which.min(loss_vec)
  opt_p = NA
  # Combine into a data frame
  df = as.data.frame(cbind(opt_m, opt_p))
  names(df) <- c("Optimal m", "Optimal p")
  # Assign a rowname
  if (is.null(rowname) == TRUE){
    # Write the row names
    rownames(df) <- c("MV CAViaR")
  }
  else {
    rownames(df) <- rowname
  }
  # Return the loss_vector and the minimzer
  return(list(opt_m, loss_vec, df))
}
#' Function that selects the optimal number of lags
#'
#' @param y - response vector
#' @param x - predictor variables
#' @param orig - forecast origin
#' @param end - ending of validation set
#' @param tau - VaR in question
#' @param low_m - low value of m to consider
#' @param high_m - high value of m to consider
#'
#' @return - returns the optimal value of m
#' @export
#'
#' @examples - opt_mp(y = pc_df[,1], x = pc_df[,-1], orig = 757, end = 1007, tau = 0.01, low_m =1, high_m  = 5, low_p = 1, high_p = 10, ar_tf = 2, mod_di = 1)
opt_mp = function(y, x, orig, end = NULL, tau, low_m = 1, high_m, low_p = 1, high_p, mod_di = 0, ar_tf = 1, print_mdl = 0, model = 1, print_mp = 0, rowname = NULL){
  # Initialize a loss matrix
  loss_mat = matrix(0, high_p-low_p + 1,high_m-low_m + 1)
  # Initialize a p vector
  p_vec = seq(low_p, high_p, by = 1)
  # Loop through and populate the loss vector
  for (i in 1:nrow(loss_mat)){
    loss_mat[i,] = opt_m(y = y, x = x, orig = orig, end = end, tau = tau, low_m = low_m, high_m  = high_m, p = i, mod_di = mod_di, ar_tf = ar_tf, print_mdl = print_mdl, model = model)[[2]]
  }
  # Find the minimizer
  opt_p = which(loss_mat == min(loss_mat), arr.ind = TRUE)[1,1]
  opt_m = which(loss_mat == min(loss_mat), arr.ind = TRUE)[1,2]
  # Print the optimal p and optimal m
  df = as.data.frame(cbind(opt_m, opt_p))
  names(df) <- c("Optimal m", "Optimal p")
  # Assign a rowname
  if (is.null(rowname) == TRUE){
    if (ar_tf == 1){
      # Write the row names
      rownames(df) <- c("MV CAViaR + AR")
    } else if (ar_tf == 2){
      # Write the row names
      rownames(df) <- c("MV CAViaR + SAV")
    } else if (ar_tf == 3){
      # Write the row names
      rownames(df) <- c("MV CAViaR + AS")
    } else {
      rownames(df) <- c("Unknown Model")
    }
  }
  else {
    rownames(df) <- rowname
  }
  # Print the df if the option is turned on
  if (print_mp == 1){
    print(df)
  }
  # Return the loss_vector and the minimzer
  return(list(opt_m, opt_p, loss_mat, df))
}
#' A function that combines optimal values of m and p into a final table
#'
#' @param m1 - the data frame from the "MV CAViaR" run
#' @param m2 - the data frame from the "MV CAViaR + AR" run
#' @param m3 - the data frame from the "MV CAViaR + SAV" run
#' @param m4 - the data frame from the "MV CAViaR + AS" run
#'
#' @return - a nicely formatted table
#' @export
#'
#' @examples - pretty_pm(opt_pred_nl[[3]], opt_pm_m1[[4]], opt_pm_m2[[4]], opt_pm_m3[[4]])
pretty_pm = function(m1, m2, m3, m4){
  # Merge the individual data frames
  pm_pretty_df = rbind(m1, m2, m3, m4)
  # Format nicely
  pm_pretty_df %>% kable(caption = "Optimal Number of Diffusion Indices (m) and Lags (p) for Different Models", digits = 0) %>% kable_styling("striped", full_width = F) %>% kable_styling() %>% footnote(general = "The MV CAViaR model doesn't have an optimal value for p because there are no AR lags in the model"
  )
  
}

#' Here is a function that runs the univariate CAViaR model 4 times
#'
#' @param df - the percent change data frame to consider
#' @param nfcst - number of forecasts to run
#' @param tau - the VaR level to consider
#' @param no_run - specifies if any models should not be run
#'
#' @return - a list of the 4 univariate model forecasts
#' @export
#'
#' @examples - aceg = gen_uv_test(pc_df, 1, 0.05, no_run = c(1,1,0,1))
gen_uv_test = function(df, nfcst, tau, no_run = c(0,0,0,0)){
  # model type (1 - SAV, 2 - AS, 3 - GARCH, 4 - ADAPTIVE) 
  # Initialize a list  
  out_list = list()
  # Run the four models - model 1; SAV
  if (no_run[1] == 0){
    uvcav_1 = rolling_predictions(df[,1], range_data = (1:length(df[,1])), nfcst = nfcst, model = 1, G = 10, col = 1, level = tau)
  }
  # Add a filler if there's no entry
  else {
    uvcav_1 = 0
  }
  # Model 2 - AS
  if (no_run[2] == 0){
    uvcav_2 = rolling_predictions(df[,1], range_data = (1:length(df[,1])), nfcst = nfcst, model = 2, G = 10, col = 1, level = tau)
  }
  else {
    uvcav_2 = 0
  }
  # Model 3 - GARCH
  if (no_run[3] == 0){
    uvcav_3 = rolling_predictions(df[,1], range_data = (1:length(df[,1])), nfcst = nfcst, model = 3, G = 10, col = 1, level = tau)
  }
  else {
    uvcav_3 = 0
  }
  # Model 4 - Adaptive
  if (no_run[4] == 0){
    uvcav_4 = rolling_predictions(df[,1], range_data = (1:length(df[,1])), nfcst = nfcst, model = 4, G = 10, col = 1, level = tau)
  }
  else {
    uvcav_4 = 0
  }
  # Export the data as a list
  return(list(uvcav_1, uvcav_2, uvcav_3, uvcav_4))
}

#' Function to plot the data which we generate in previous functions
#'
#' @param plot_matrix - matrix with the data to plot
#' @param norm_value - what to subtact from the data to make it on a percentage change basis. Default is 100.
#'
#' @return 
#' @export - a plot of the data by diffusion index number
#'
#' @examples = plt_data(plot_mtx[[1]]), abc = plt_data(plot_mat, tau = 0.01)
plt_data = function(plot_matrix, tau, resp_var, ntest){
  # Establish a maximum and minimum value
  max_val = max(plot_matrix[,1:ncol(plot_matrix)])
  min_val = min(plot_matrix[,1:ncol(plot_matrix)])
  # Calculate inital and ending time value
  start = index(plot_matrix)[1]
  end = index(plot_matrix)[nrow(plot_matrix)]
  ind_vals = index(plot_matrix) - start
  # Create an initial plot and add lines
    for (i in 1:ncol(plot_matrix)){
      if (i == 1){
        # 4/2/2020 - fixing the index
        plot.ts(ind_vals,plot_matrix[,i], type = "l", xlab = paste("Days Since", as.Date(start)), ylab = "Percent Change in PG", ylim = c(min_val,max_val), lwd = 1, main = paste("Predicting", resp_var, "Returns from", as.Date(start), "to", as.Date(end)), sub = paste("The VaR Level is ", 100*tau, "%", "; There are ", ntest, " Trading Days Plotted Above", sep = ""))
        # plot.ts(index(plot_matrix), plot_matrix[,i], type = "l", xlab = "Trading Days", ylab = "Percent Change in PG", ylim = c(min_val,max_val), lwd = 1, main = "Predicting PG Returns Over Last 250 Trading Days in 2008", sub = paste("The VaR Level is ", 100*tau, "%", sep = ""))
    } else if(i %in% seq(2,8,1)) {
        lines(ind_vals,plot_matrix[,i], col = i-1, lty = 2)
    } else {
        lines(ind_vals,plot_matrix[,i], col = i-1, lty = 2, lwd = 2)
    }
    }
  # Define a sequence for plotting
  plot_seq = seq(1, ncol(plot_matrix))
  legend("topleft", legend = c(colnames(plot_matrix)), col = plot_seq, lty = c(1, rep(2, 7), rep(3, ifelse(ncol(plot_matrix)-8 <= 0, 0, ncol(plot_matrix)-8))), lwd = c(1, rep(1, 7), rep(2, ifelse(ncol(plot_matrix)-8 <= 0, 0, ncol(plot_matrix)-8))))
  # Add a line for 0
  # abline(h = 0, col = "black", lty = 2)
}


#' A function to calculate losses based on the test sample
#'
#' @param true_vec - the true vector of returns
#' @param pred_vec - the predicted vector from the model runs
#' @param tau - VaR level. Must match what the model used
#'
#' @return - total losses and the entire loss vector
#' @export
#'
#' @examples
loss_test = function(true_vec, pred_vec, tau){
  # Initialize a loss vector
  lvec = rep(0, length(true_vec))
  # Initialize a break vector to see when VaR is broken
  bvec = rep(0, length(true_vec))
  for (i in 1:length(true_vec)){
    # Calculate an indicator variable
    bvec[i] = ifelse(true_vec[i] < pred_vec[i], 1,0)
    # Use indicator in function below
    lvec[i] = (tau - bvec[i])*(true_vec[i] - pred_vec[i])
  }
  # Add up the losses
  # sumloss = sum(lvec)/length(lvec)
  sumloss = sum(lvec)
  # Add up the VaR breakage
  varbreak = sum(bvec)/length(bvec)
  return(list(sumloss,lvec, varbreak, bvec))
}
#' A function to calculate losses based on the plot matrix
#'
#' @param data_mat - a matrix of forecasted VaR values, with the true value in the first column
#' @param tau - VaR level. Must match what the model used
#'
#' @return - a list of four items. 
#' 1 = a vector of the losses of all models. 
#' 2 = a vector showing the percentage of VaR breaks by model
#' 3 = the loss matrix
#' 4 = the break matrix
#' @export
#'
#' @examples
gen_loss_test = function(data_mat, tau){
  # Initialize loss and break matrices
  lmat = bmat = matrix(0, nrow = nrow(data_mat), ncol = ncol(data_mat)-1)
  # bvec = rep(0, length(true_vec))
  # Populate the matrices
  for (i in 1:nrow(lmat)){
    for (j in 1:(ncol(lmat))){
      # Calculate an indicator variable
      bmat[i,j] = ifelse(data_mat[i,1] < data_mat[i,j+1], 1,0)
      # Use indicator in function below
      lmat[i,j] = (tau - bmat[i,j])*(data_mat[i,1] - data_mat[i,j+1])
    }    
  }
  # Add up the losses
  sumloss = colSums(lmat)
  # Add up the VaR breakage
  varbreak = colSums(bmat)/nrow(bmat)
  return(list(sumloss, varbreak, lmat, bmat))
}
#' A function to make a nice comparison of losses
#'
#' @param data_mat - input data matrix used in the calculation of losses
#' @param loss_list - a list of the losses calculated from the CAViaR function
#' @param tau - the risk level used
#' @param ntest - the number of test points
#'
#' @return
#' @export - returns a nicely formatted table
#'
#' @examples - pretty_tables(plot_mat, l_list, tau = 0.01)
pretty_tables = function(data_mat, loss_list, tau, ntest){
  # Combine into a data frame
  df = as.data.frame(rbind(loss_list[[1]], loss_list[[2]]))
  # Calculate inital and ending time value
  start = index(data_mat)[1]
  end = index(data_mat)[nrow(data_mat)]
  # Add row/column names
  colnames(df) <- colnames(data_mat[,-1])
  rownames(df) <- c("Losses", "VaR Breaks (%)")
  # Convert to a table
  df %>% kable(caption = paste("Comparison of VaR Methods for a ", tau*100, "% VaR", sep = ""), digits = 3) %>% kable_styling("striped", full_width = F) %>% kable_styling() %>% footnote(general = paste("Calculated using", ntest, "trading days from", as.Date(start), "to", as.Date(end)))
}
#' A dressed up version of the export function
#'
#' @param var_file - file to export
#' @param path - filepath
#' @param filename - name of the file, ending with .CSV
#'
#' @return
#' @export - exported CSV file
#'
#' @examples - exp_func(var_file = var_1pc_2016_usetf[[1]], path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/", filename = "TEST.csv")
exp_func = function(var_file, path, filename){
  # Write a zoo
  write.zoo(var_file, paste0(path, filename), quote = FALSE, sep = ",")
}

# exp_func(var_file = var_1pc_2016_usetf[[1]], path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/", filename = "TEST.csv")

#' This is the "master" function where we'll evaluate the importance of the VaR model over several time periods
#'
#' @param symbol_list - a list of symbols to feed into the model 
#' @param resp_var - the response variable
#' @param compl_case - should the model require complete cases? Default value is 1.
#' @param adj_close - use adjusted close price for the predictors? Default value is 1.
#' @param resp_adj_close - use adjusted close price for the response? Default value is 1.
#' @param start_date - start date to pull data from
#' @param end_date - end date to pull data from
#' @param nval - number of validation points to use
#' @param ntest - number of test points to use
#' @param tau - VaR level to use
#' @param low_m - low number of predictors to test
#' @param high_m  - low number of predictors to test
#' @param uv_list - a list of a pre-run univariate model. If a data frame is not provided, the lengthy uv model will run 
#' @param no_run - things not to run in the model
#' @param low_p - low value for number of lags
#' @param high_p - high value for number of lags
#' @param na_interp - should the function interpolate NA's
#' @param print_mdl - print the model summaries?
#' @param print_mp - print the optimal values for p and m
#' @param lag_pred - do you want to lag the m predictors (default is 1; strongly recommended)
#' @param rowname - what to name the rows of the nice p and m matrix
#' @param export_csv - do you want to export a CSV? Default is 1.
#' @param path - path to export the CSV
#' @param filename - what to name the CSV
#'
#' @return - a list of the plot matrix, a plot, a list with losses, and a table
#' @export - a plot and a table
#'
#' @examples - cav_simul(c("DIS", "GE", "IBM", "MMM", "XOM"), resp_var = "PG", start_date = "2004-01-01", end_date = "2008-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 5, tau = 0.01, uv_list = uv_cav_list)
cav_simul = function(symbol_list, resp_var, compl_case = 1, adj_close = 1, resp_adj_close = 1, start_date = "1900-01-01", end_date = Sys.Date(), nval, ntest, tau, low_m = 1, high_m, low_p = 1, high_p, uv_list = NULL, no_run = c(0,0,0,0), na_interp = TRUE, print_mdl = 0, print_mp = 0, lag_pred = 1, rowname = NULL, export_csv = 1, path, filename){
  # Select data parameters, pull the data, and percent change the data
  df = diff_index_df(symbol_list = symbol_list, resp_var = resp_var, compl_case = compl_case, adj_close = adj_close, resp_adj_close = resp_adj_close, start_date = start_date, end_date = end_date, lag_pred = lag_pred)
  # Take the percent change of the data
  pc_df = pc_diff_index(df)
  # Extract the legnth of the data frame
  nr = test_end = nrow(pc_df)
  # Calculate the start of the val period, the end of the val period, and the beginning and end of test period
  test_orig = test_end - ntest
  val_end = test_orig
  val_orig = test_orig - nval
  # Test for the optimal number of parameters
  opt_pred_nl = opt_m(y = pc_df[,1], x = pc_df[,-1], orig = val_orig, end = val_end, tau = tau, low_m = low_m, high_m = high_m, rowname = rowname)
  opt_pred_art1 = opt_mp(y = pc_df[,1], x = pc_df[,-1], orig = val_orig, end = val_end, tau = tau, low_m = low_m, high_m = high_m, low_p = low_p, high_p = high_p,mod_di = 1, ar_tf = 1, print_mdl = print_mdl, print_mp = print_mp, rowname = rowname)
  opt_pred_art2 = opt_mp(y = pc_df[,1], x = pc_df[,-1], orig = val_orig, end = val_end, tau = tau, low_m = low_m, high_m = high_m, low_p = low_p, high_p = high_p,mod_di = 1, ar_tf = 2, print_mdl = print_mdl, print_mp = print_mp, rowname = rowname)
  opt_pred_art3 = opt_mp(y = pc_df[,1], x = pc_df[,-1], orig = val_orig, end = val_end, tau = tau, low_m = low_m, high_m = high_m, low_p = low_p, high_p = high_p, mod_di = 1, ar_tf = 3, print_mdl = print_mdl, print_mp = print_mp, rowname = rowname)
  # gen_uv_test(pc_df, 1, 0.05, no_run = c(1,1,0,1))
  # Use the above forecasts to input into the above
  mv_fcst = mod_di(pc_df[,1], pc_df[,-1], orig = test_orig, m = opt_pred_nl[[1]], tau = tau, print_mdl = print_mdl)
  mv_fcst_art1 = mod_di_wl(pc_df[,1], pc_df[,-1], orig = test_orig, m = opt_pred_art1[[1]], p = opt_pred_art1[[2]], tau = tau, ar_tf = 1, print_mdl = print_mdl)
  mv_fcst_art2 = mod_di_wl(pc_df[,1], pc_df[,-1], orig = test_orig, m = opt_pred_art2[[1]], p = opt_pred_art2[[2]], tau = tau, ar_tf = 2, print_mdl = print_mdl)
  mv_fcst_art3 = mod_di_wl(pc_df[,1], pc_df[,-1], orig = test_orig, m = opt_pred_art3[[1]], p = opt_pred_art3[[2]], tau = tau, ar_tf = 3, print_mdl = print_mdl)
  # Calculate the number of predictions
  if (is.null(uv_list) == TRUE){
    # Print a warning
    print("WARNING: Not supplying an input data frame will require this function to run for a significant amount of time (1hr+)")
    # Call the function
    # gen_uv_test = function(df, nfcst, tau, no_run = c(0,0,0,0)){
    # print(head(pc_df))
    uv_list = gen_uv_test(df = pc_df, nfcst = ntest, tau = tau, no_run = no_run)
    # Add to a data frame
    # Incorporate the rolling predictions function results here
  plot_mat = cbind(pc_df[(test_orig+1):nrow(pc_df),1], mv_fcst$yhat[1:ntest], mv_fcst_art1$yhat[1:ntest], mv_fcst_art2$yhat[1:ntest], mv_fcst_art3$yhat[1:ntest], uv_list[[1]][(test_orig+1):test_end]*(-1), uv_list[[2]][(test_orig+1):test_end]*(-1), uv_list[[3]][(test_orig+1):test_end]*(-1), uv_list[[4]][(test_orig+1):test_end]*(-1))
  } else {
    # Assign the columns of the data frame
    # head(var_5pc_2010_usetf[[1]][,6:9])
    # model type (1 - SAV, 2 - AS, 3 - GARCH, 4 - ADAPTIVE) 
    # test_df = head(var_5pc_2010_usetf[[1]][,6:9])
    # test_df$SAV
    # test_df$`Abs. Slope`
    # test_df$`Ind. GARCH`
    # test_df$Adaptive
    plot_mat = cbind(pc_df[(test_orig+1):nrow(pc_df),1], mv_fcst$yhat[1:ntest], mv_fcst_art1$yhat[1:ntest], mv_fcst_art2$yhat[1:ntest], mv_fcst_art3$yhat[1:ntest], uv_list$SAV, uv_list$`Abs. Slope`, uv_list$`Ind. GARCH`, uv_list$Adaptive)
  }
  # Count the NAs and print a warning
  print(paste("NOTE: There are ", sum(is.na(plot_mat)), " NA(s) in the dataset", sep = ""))
  # Linearly interpolate the NAs
  if (na_interp == TRUE){
    # Assign the plot matrix to a new value
    plot_mat_na <- plot_mat
    # Print a warning
    print("WARNING: There were missing values in the plot matrix.")
    # Interpolate the NA's
    for (i in 1:ncol(plot_mat_na)){
      # Interpolate the data
      plot_mat[,i] <- na.approx(plot_mat_na[,i])
    }
  }
  # model type (1 - SAV, 2 - AS, 3 - GARCH, 4 - ADAPTIVE)
  # Add descriptive titles onto the plot_mat
  colnames(plot_mat) <- c(resp_var, "MV CAViaR", "MV CAViaR + AR", "MV CAViaR + SAV", "MV CAViaR + AS", "SAV", "Abs. Slope", "Ind. GARCH", "Adaptive")
  # colnames(plot_mat) <- c("SPY", "MV CAViaR", "MV CAViaR + AR", "MV CAViaR + SAV", "MV CAViaR + AS", "SAV", "Abs. Slope", "Ind. GARCH", "Adaptive")
  # Plot everything
  plot = plt_data(plot_mat, tau = tau, resp_var = resp_var, ntest = ntest)
  # Calculate losses
  l_list = gen_loss_test(plot_mat, tau = tau)
  # Put into tables
  tables = pretty_tables(plot_mat, l_list, tau = tau, ntest = ntest)
  # Run the function for optimal p and m
  pm_table = pretty_pm(opt_pred_nl[[3]], opt_pred_art1[[4]], opt_pred_art2[[4]], opt_pred_art3[[4]])
  # Export the matrix
  if (export_csv == 1){
    exp_func(var_file = plot_mat, path, filename)
  }
  # Print the tables and the plot
  print(plot)
  print(tables)
  print(pm_table)
  return(list(plot_mat, plot, l_list, tables, plot_mat_na, pm_table))
}
#' A function to input the VaR files, plot them and generate tables
#'
#' @param file_path - file path to use
#' @param filename - name of the file
#' @param tau - quantile to use
#' @param resp_var - response variable to use in the plot
#' @param ntest - number of test points
#' @param cn_input - column name inputs
#'
#' @return - a list of the xts file, the plot, the loss list, and tables
#' @export - a plot and tables
#'
#' @examples - test = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/","var_1pc_2008_us_etf.csv", 0.01)
var_input_disp = function(file_path, filename, tau, resp_var = "SPY", ntest = 250, cn_input = c("SPY", "MV CAViaR", "MV CAViaR + AR", "MV CAViaR + SAV", "MV CAViaR + AS", "SAV", "Abs. Slope", "Ind. GARCH", "Adaptive")){
# var_input_disp = function(file_path, filename, tau, resp_var = "SPY", ntest = 250, cn_input = c("SPY", "MV CAViaR", "MV CAViaR + AR", "MV CAViaR + SAV", "MV CAViaR + AS", "SAV", "Abs. Slope", "Ind. GARCH", "Adaptive")){
  # Import data
  plot_mat = read.csv(paste0(file_path,filename), sep = ",", header = T, stringsAsFactors = FALSE)
  # Fix date format
  plot_mat$Index = as.Date(plot_mat$Index)
  # Convert to an xts
  plot_mat = xts(plot_mat[,-1], order.by = plot_mat[,1])
  # Fix column names
  colnames(plot_mat) <- cn_input
  # Plot everything
  plt_data(plot_mat, tau = tau, resp_var = resp_var, ntest = ntest)
  # plot = plt_data(plot_mat, tau = tau, resp_var = resp_var, ntest = ntest)
  # Calculate losses
  l_list = gen_loss_test(plot_mat, tau = tau)
  # Put into tables
  df = as.data.frame(rbind(l_list[[1]], l_list[[2]]))
  # Calculate inital and ending time value
  start = index(plot_mat)[1]
  end = index(plot_mat)[nrow(plot_mat)]
  # Add row/column names
  colnames(df) <- colnames(plot_mat[,-1])
  rownames(df) <- c("Losses", "VaR Breaks (%)")
  # Convert to a table
  print(df, digits = 3)
  # print(formattable(df, digits = 3))
  # df %>% kable(caption = paste("Comparison of VaR Methods for a ", tau*100, "% VaR", sep = ""), digits = 3) %>% kable_styling("striped", full_width = F) %>% kable_styling() %>% footnote(general = paste("Calculated using", ntest, "trading days from", as.Date(start), "to", as.Date(end)))
  # pm_table = pretty_tables(plot_mat, l_list, tau = tau, ntest = ntest)
  # Print the tables and the plot
  # print(plot)
  # print(tables)
  # print(pm_table)
  # Return the xts, the plot, the loss list, and the tables
  return(list(plot_mat))
  # return(list(plot_mat, plot, l_list, tables))
}
# return(list(plot_mat, plot, l_list, tables))

# Call the above function
v1_2008_usetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/","var_1pc_2008_us_etf.csv", 0.01)
# pretty_tables(v1_2008_usetf[[1]], v1_2008_usetf[[3]], tau = 0.01, ntest = 250)
v5_2008_usetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/","var_5pc_2008_us_etf.csv", 0.05)
v10_2008_usetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/","var_10pc_2008_us_etf.csv", 0.10)

# head(v10_2008_usetf[[1]])
# v10_2008_usetf
# 1%, 5%, 10% VaR - 2008 - 1st set of predictors
# var_1pc_2008_us_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE"), resp_var = "SPY", start_date = "2004-01-01", end_date = "2008-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 9, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/", filename = "var_1pc_2008_us_etf.csv", uv_list = var_1pc_2008_usetf[[1]])

# var_5pc_2008_us_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE"), resp_var = "SPY", start_date = "2004-01-01", end_date = "2008-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 9, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/", filename = "var_5pc_2008_us_etf.csv", uv_list = var_5pc_2008_usetf[[1]])

# var_10pc_2008_us_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE"), resp_var = "SPY", start_date = "2004-01-01", end_date = "2008-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 9, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/", filename = "var_10pc_2008_us_etf.csv", uv_list = var_10pc_2008_usetf[[1]])
# Call the above function
v1_2008_globetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/","var_1pc_2008_glob_etf.csv", 0.01)
v5_2008_globetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/","var_5pc_2008_glob_etf.csv", 0.05)
v10_2008_globetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/","var_10pc_2008_glob_etf.csv", 0.10)
# 1%, 5%, 10% VaR - 2008 - 2nd set of predictors
# var_1pc_2008_glob_etf = cav_simul(c("JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC"), resp_var = "SPY", start_date = "2004-01-01", end_date = "2008-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 10, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/", filename = "var_1pc_2008_glob_etf.csv", uv_list = var_1pc_2008_usetf[[1]])

# var_5pc_2008_glob_etf = cav_simul(c("JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC"), resp_var = "SPY", start_date = "2004-01-01", end_date = "2008-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 10, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/", filename = "var_5pc_2008_glob_etf.csv", uv_list = var_5pc_2008_usetf[[1]])

# var_10pc_2008_glob_etf = cav_simul(c("JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC"), resp_var = "SPY", start_date = "2004-01-01", end_date = "2008-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 10, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/", filename = "var_10pc_2008_glob_etf.csv", uv_list = var_10pc_2008_usetf[[1]])
# 1%, 5%, 10% VaR - 2008 - 3rd set of predictors
# var_1pc_2008_comm_etf = cav_simul(c("DBA", "DBC", "DBE", "DBB"), resp_var = "SPY", start_date = "2004-01-01", end_date = "2008-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_comm_ETF_runs/", filename = "var_1pc_2008_comm_etf.csv", uv_list = var_1pc_2008_usetf[[1]])

# var_5pc_2008_comm_etf = cav_simul(c("DBA", "DBC", "DBE", "DBB"), resp_var = "SPY", start_date = "2004-01-01", end_date = "2008-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_comm_ETF_runs/", filename = "var_5pc_2008_comm_etf.csv", uv_list = var_5pc_2008_usetf[[1]])

# var_10pc_2008_comm_etf = cav_simul(c("DBA", "DBC", "DBE", "DBB"), resp_var = "SPY", start_date = "2004-01-01", end_date = "2008-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_comm_ETF_runs/", filename = "var_10pc_2008_comm_etf.csv", uv_list = var_10pc_2008_usetf[[1]])
# Call the above function
v1_2008_bondetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/","var_1pc_2008_bond_etf.csv", 0.01)
v5_2008_bondetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/","var_5pc_2008_bond_etf.csv", 0.05)
v10_2008_bondetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/","var_10pc_2008_bond_etf.csv", 0.10)
# iShares 1-3 Year Treasury Bond Fund (SHY)
# iShares 7-10 Year Treasury Bond Fund (IEF)
# iShares 20+ Year Treasury Bond Fund (TLT)
# iShares iBoxx $ Investment Grade Corporate Bond ETF (LQD)

# 1%, 5%, 10% VaR - 2008 - 4th set of predictors
# var_1pc_2008_bond_etf = cav_simul(c("SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2004-01-01", end_date = "2008-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/", filename = "var_1pc_2008_bond_etf.csv", uv_list = var_1pc_2008_usetf[[1]])

# var_5pc_2008_bond_etf = cav_simul(c("SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2004-01-01", end_date = "2008-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/", filename = "var_5pc_2008_bond_etf.csv", uv_list = var_5pc_2008_usetf[[1]])

# var_10pc_2008_bond_etf = cav_simul(c("SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2004-01-01", end_date = "2008-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/", filename = "var_10pc_2008_bond_etf.csv", uv_list = var_10pc_2008_usetf[[1]])
# Call the above function
v1_2008_alletf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/","var_1pc_2008_all_etf.csv", 0.01)
v5_2008_alletf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/","var_5pc_2008_all_etf.csv", 0.05)
v10_2008_alletf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/","var_10pc_2008_all_etf.csv", 0.10)
# 1%, 5%, 10% VaR - 2008 - 5th set of predictors
# var_1pc_2008_all_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE", "JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC", "SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2004-01-01", end_date = "2008-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 23, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/", filename = "var_1pc_2008_all_etf.csv", uv_list = var_1pc_2008_usetf[[1]])

# var_5pc_2008_all_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE", "JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC", "SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2004-01-01", end_date = "2008-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 23, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/", filename = "var_5pc_2008_all_etf.csv", uv_list = var_5pc_2008_usetf[[1]])

# var_10pc_2008_all_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE", "JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC", "SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2004-01-01", end_date = "2008-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 23, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/", filename = "var_10pc_2008_all_etf.csv", uv_list = var_10pc_2008_usetf[[1]])
# Call the above function
v1_2010_usetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/","var_1pc_2010_us_etf.csv", 0.01)
v5_2010_usetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/","var_5pc_2010_us_etf.csv", 0.05)
v10_2010_usetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/","var_10pc_2010_us_etf.csv", 0.10)
# 1%, 5%, 10% VaR - 2010 - 1st set of predictors
# var_1pc_2010_us_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE"), resp_var = "SPY", start_date = "2006-01-01", end_date = "2010-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 9, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/", filename = "var_1pc_2010_us_etf.csv", uv_list = var_1pc_2010_usetf[[1]])

# var_5pc_2010_us_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE"), resp_var = "SPY", start_date = "2006-01-01", end_date = "2010-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 9, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/", filename = "var_5pc_2010_us_etf.csv", uv_list = var_5pc_2010_usetf[[1]])

# var_10pc_2010_us_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE"), resp_var = "SPY", start_date = "2006-01-01", end_date = "2010-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 9, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/", filename = "var_10pc_2010_us_etf.csv", uv_list = var_10pc_2010_usetf[[1]])
# Call the above function
v1_2010_globetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/","var_1pc_2010_glob_etf.csv", 0.01)
v5_2010_globetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/","var_5pc_2010_glob_etf.csv", 0.05)
v10_2010_globetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/","var_10pc_2010_glob_etf.csv", 0.10)
# 1%, 5%, 10% VaR - 2010 - 2nd set of predictors
# var_1pc_2010_glob_etf = cav_simul(c("JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC"), resp_var = "SPY", start_date = "2006-01-01", end_date = "2010-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 10, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/", filename = "var_1pc_2010_glob_etf.csv", uv_list = var_1pc_2010_usetf[[1]])

# var_5pc_2010_glob_etf = cav_simul(c("JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC"), resp_var = "SPY", start_date = "2006-01-01", end_date = "2010-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 10, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/", filename = "var_5pc_2010_glob_etf.csv", uv_list = var_5pc_2010_usetf[[1]])

# var_10pc_2010_glob_etf = cav_simul(c("JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC"), resp_var = "SPY", start_date = "2006-01-01", end_date = "2010-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 10, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/", filename = "var_10pc_2010_glob_etf.csv", uv_list = var_10pc_2010_usetf[[1]])
# 1%, 5%, 10% VaR - 2010 - 3rd set of predictors
# var_1pc_2010_comm_etf = cav_simul(c("DBA", "DBC", "DBE", "DBB"), resp_var = "SPY", start_date = "2006-01-01", end_date = "2010-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_comm_ETF_runs/", filename = "var_1pc_2010_comm_etf.csv", uv_list = var_1pc_2010_usetf[[1]])

# var_5pc_2010_comm_etf = cav_simul(c("DBA", "DBC", "DBE", "DBB"), resp_var = "SPY", start_date = "2006-01-01", end_date = "2010-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_comm_ETF_runs/", filename = "var_5pc_2010_comm_etf.csv", uv_list = var_5pc_2010_usetf[[1]])

# var_10pc_2010_comm_etf = cav_simul(c("DBA", "DBC", "DBE", "DBB"), resp_var = "SPY", start_date = "2006-01-01", end_date = "2010-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_comm_ETF_runs/", filename = "var_10pc_2010_comm_etf.csv", uv_list = var_10pc_2010_usetf[[1]])
# Call the above function
v1_2010_bondetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/","var_1pc_2010_bond_etf.csv", 0.01)
v5_2010_bondetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/","var_5pc_2010_bond_etf.csv", 0.05)
v10_2010_bondetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/","var_10pc_2010_bond_etf.csv", 0.10)
# iShares 1-3 Year Treasury Bond Fund (SHY)
# iShares 7-10 Year Treasury Bond Fund (IEF)
# iShares 20+ Year Treasury Bond Fund (TLT)
# iShares iBoxx $ Investment Grade Corporate Bond ETF (LQD)

# 1%, 5%, 10% VaR - 2010 - 4th set of predictors
# var_1pc_2010_bond_etf = cav_simul(c("SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2006-01-01", end_date = "2010-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/", filename = "var_1pc_2010_bond_etf.csv", uv_list = var_1pc_2010_usetf[[1]])

# var_5pc_2010_bond_etf = cav_simul(c("SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2006-01-01", end_date = "2010-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/", filename = "var_5pc_2010_bond_etf.csv", uv_list = var_5pc_2010_usetf[[1]])

# var_10pc_2010_bond_etf = cav_simul(c("SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2006-01-01", end_date = "2010-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/", filename = "var_10pc_2010_bond_etf.csv", uv_list = var_10pc_2010_usetf[[1]])
# Call the above function
v1_2010_alletf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/","var_1pc_2010_all_etf.csv", 0.01)
v5_2010_alletf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/","var_5pc_2010_all_etf.csv", 0.05)
v10_2010_alletf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/","var_10pc_2010_all_etf.csv", 0.10)
# 1%, 5%, 10% VaR - 2010 - 5th set of predictors
# var_1pc_2010_all_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE", "JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC", "SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2006-01-01", end_date = "2010-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 23, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/", filename = "var_1pc_2010_all_etf.csv", uv_list = var_1pc_2010_usetf[[1]])

# var_5pc_2010_all_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE", "JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC", "SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2006-01-01", end_date = "2010-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 23, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/", filename = "var_5pc_2010_all_etf.csv", uv_list = var_5pc_2010_usetf[[1]])

# var_10pc_2010_all_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE", "JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC", "SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2006-01-01", end_date = "2010-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 23, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/", filename = "var_10pc_2010_all_etf.csv", uv_list = var_10pc_2010_usetf[[1]])
# Call the above function
v1_2014_usetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/","var_1pc_2014_us_etf.csv", 0.01)
v5_2014_usetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/","var_5pc_2014_us_etf.csv", 0.05)
v10_2014_usetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/","var_10pc_2014_us_etf.csv", 0.10)
# 1%, 5%, 10% VaR - 2014 - 1st set of predictors
# var_1pc_2014_us_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE"), resp_var = "SPY", start_date = "2010-01-01", end_date = "2014-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 9, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/", filename = "var_1pc_2014_us_etf.csv", uv_list = var_1pc_2014_usetf[[1]])

# var_5pc_2014_us_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE"), resp_var = "SPY", start_date = "2010-01-01", end_date = "2014-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 9, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/", filename = "var_5pc_2014_us_etf.csv", uv_list = var_5pc_2014_usetf[[1]])

# var_10pc_2014_us_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE"), resp_var = "SPY", start_date = "2010-01-01", end_date = "2014-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 9, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/", filename = "var_10pc_2014_us_etf.csv", uv_list = var_10pc_2014_usetf[[1]])
# Call the above function
v1_2014_globetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/","var_1pc_2014_glob_etf.csv", 0.01)
v5_2014_globetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/","var_5pc_2014_glob_etf.csv", 0.05)
v10_2014_globetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/","var_10pc_2014_glob_etf.csv", 0.10)
# 1%, 5%, 10% VaR - 2014 - 2nd set of predictors
# var_1pc_2014_glob_etf = cav_simul(c("JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC"), resp_var = "SPY", start_date = "2010-01-01", end_date = "2014-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 10, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/", filename = "var_1pc_2014_glob_etf.csv", uv_list = var_1pc_2014_usetf[[1]])

# var_5pc_2014_glob_etf = cav_simul(c("JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC"), resp_var = "SPY", start_date = "2010-01-01", end_date = "2014-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 10, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/", filename = "var_5pc_2014_glob_etf.csv", uv_list = var_5pc_2014_usetf[[1]])

# var_10pc_2014_glob_etf = cav_simul(c("JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC"), resp_var = "SPY", start_date = "2010-01-01", end_date = "2014-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 10, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/", filename = "var_10pc_2014_glob_etf.csv", uv_list = var_10pc_2014_usetf[[1]])
# 1%, 5%, 10% VaR - 2014 - 3rd set of predictors
# var_1pc_2014_comm_etf = cav_simul(c("DBA", "DBC", "DBE", "DBB"), resp_var = "SPY", start_date = "2010-01-01", end_date = "2014-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_comm_ETF_runs/", filename = "var_1pc_2014_comm_etf.csv", uv_list = var_1pc_2014_usetf[[1]])

# var_5pc_2014_comm_etf = cav_simul(c("DBA", "DBC", "DBE", "DBB"), resp_var = "SPY", start_date = "2010-01-01", end_date = "2014-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_comm_ETF_runs/", filename = "var_5pc_2014_comm_etf.csv", uv_list = var_5pc_2014_usetf[[1]])

# var_10pc_2014_comm_etf = cav_simul(c("DBA", "DBC", "DBE", "DBB"), resp_var = "SPY", start_date = "2010-01-01", end_date = "2014-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_comm_ETF_runs/", filename = "var_10pc_2014_comm_etf.csv", uv_list = var_10pc_2014_usetf[[1]])
# Call the above function
v1_2014_bondetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/","var_1pc_2014_bond_etf.csv", 0.01)
v5_2014_bondetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/","var_5pc_2014_bond_etf.csv", 0.05)
v10_2014_bondetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/","var_10pc_2014_bond_etf.csv", 0.10)
# iShares 1-3 Year Treasury Bond Fund (SHY)
# iShares 7-10 Year Treasury Bond Fund (IEF)
# iShares 20+ Year Treasury Bond Fund (TLT)
# iShares iBoxx $ Investment Grade Corporate Bond ETF (LQD)

# 1%, 5%, 10% VaR - 2014 - 4th set of predictors
# var_1pc_2014_bond_etf = cav_simul(c("SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2010-01-01", end_date = "2014-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/", filename = "var_1pc_2014_bond_etf.csv", uv_list = var_1pc_2014_usetf[[1]])

# var_5pc_2014_bond_etf = cav_simul(c("SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2010-01-01", end_date = "2014-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/", filename = "var_5pc_2014_bond_etf.csv", uv_list = var_5pc_2014_usetf[[1]])

# var_10pc_2014_bond_etf = cav_simul(c("SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2010-01-01", end_date = "2014-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/", filename = "var_10pc_2014_bond_etf.csv", uv_list = var_10pc_2014_usetf[[1]])
# Call the above function
v1_2014_alletf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/","var_1pc_2014_all_etf.csv", 0.01)
v5_2014_alletf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/","var_5pc_2014_all_etf.csv", 0.05)
v10_2014_alletf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/","var_10pc_2014_all_etf.csv", 0.10)
# 1%, 5%, 10% VaR - 2014 - 5th set of predictors
# var_1pc_2014_all_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE", "JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC", "SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2010-01-01", end_date = "2014-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 23, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/", filename = "var_1pc_2014_all_etf.csv", uv_list = var_1pc_2014_usetf[[1]])

# var_5pc_2014_all_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE", "JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC", "SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2010-01-01", end_date = "2014-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 23, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/", filename = "var_5pc_2014_all_etf.csv", uv_list = var_5pc_2014_usetf[[1]])

# var_10pc_2014_all_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE", "JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC", "SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2010-01-01", end_date = "2014-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 23, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/", filename = "var_10pc_2014_all_etf.csv", uv_list = var_10pc_2014_usetf[[1]])
# Call the above function
v1_2016_usetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/","var_1pc_2016_us_etf.csv", 0.01)
v5_2016_usetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/","var_5pc_2016_us_etf.csv", 0.05)
v10_2016_usetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/","var_10pc_2016_us_etf.csv", 0.10)
# 1%, 5%, 10% VaR - 2016 - 1st set of predictors
# var_1pc_2016_us_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE"), resp_var = "SPY", start_date = "2012-01-01", end_date = "2016-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 9, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/", filename = "var_1pc_2016_us_etf.csv", uv_list = var_1pc_2016_usetf[[1]])

# var_5pc_2016_us_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE"), resp_var = "SPY", start_date = "2012-01-01", end_date = "2016-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 9, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/", filename = "var_5pc_2016_us_etf.csv", uv_list = var_5pc_2016_usetf[[1]])

# var_10pc_2016_us_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE"), resp_var = "SPY", start_date = "2012-01-01", end_date = "2016-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 9, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/", filename = "var_10pc_2016_us_etf.csv", uv_list = var_10pc_2016_usetf[[1]])
# Call the above function
v1_2016_globetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/","var_1pc_2016_glob_etf.csv", 0.01)
v5_2016_globetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/","var_5pc_2016_glob_etf.csv", 0.05)
v10_2016_globetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/","var_10pc_2016_glob_etf.csv", 0.10)
# 1%, 5%, 10% VaR - 2016 - 2nd set of predictors
# var_1pc_2016_glob_etf = cav_simul(c("JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC"), resp_var = "SPY", start_date = "2012-01-01", end_date = "2016-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 10, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/", filename = "var_1pc_2016_glob_etf.csv", uv_list = var_1pc_2016_usetf[[1]])

# var_5pc_2016_glob_etf = cav_simul(c("JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC"), resp_var = "SPY", start_date = "2012-01-01", end_date = "2016-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 10, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/", filename = "var_5pc_2016_glob_etf.csv", uv_list = var_5pc_2016_usetf[[1]])

# var_10pc_2016_glob_etf = cav_simul(c("JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC"), resp_var = "SPY", start_date = "2012-01-01", end_date = "2016-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 10, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/", filename = "var_10pc_2016_glob_etf.csv", uv_list = var_10pc_2016_usetf[[1]])
# 1%, 5%, 10% VaR - 2016 - 3rd set of predictors
# var_1pc_2016_comm_etf = cav_simul(c("DBA", "DBC", "DBE", "DBB"), resp_var = "SPY", start_date = "2012-01-01", end_date = "2016-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_comm_ETF_runs/", filename = "var_1pc_2016_comm_etf.csv", uv_list = var_1pc_2016_usetf[[1]])

# var_5pc_2016_comm_etf = cav_simul(c("DBA", "DBC", "DBE", "DBB"), resp_var = "SPY", start_date = "2012-01-01", end_date = "2016-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_comm_ETF_runs/", filename = "var_5pc_2016_comm_etf.csv", uv_list = var_5pc_2016_usetf[[1]])

# var_10pc_2016_comm_etf = cav_simul(c("DBA", "DBC", "DBE", "DBB"), resp_var = "SPY", start_date = "2012-01-01", end_date = "2016-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_comm_ETF_runs/", filename = "var_10pc_2016_comm_etf.csv", uv_list = var_10pc_2016_usetf[[1]])
# Call the above function
v1_2016_bondetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/","var_1pc_2016_bond_etf.csv", 0.01)
v5_2016_bondetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/","var_5pc_2016_bond_etf.csv", 0.05)
v10_2016_bondetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/","var_10pc_2016_bond_etf.csv", 0.10)
# iShares 1-3 Year Treasury Bond Fund (SHY)
# iShares 7-10 Year Treasury Bond Fund (IEF)
# iShares 20+ Year Treasury Bond Fund (TLT)
# iShares iBoxx $ Investment Grade Corporate Bond ETF (LQD)

# 1%, 5%, 10% VaR - 2016 - 4th set of predictors
# var_1pc_2016_bond_etf = cav_simul(c("SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2012-01-01", end_date = "2016-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/", filename = "var_1pc_2016_bond_etf.csv", uv_list = var_1pc_2016_usetf[[1]])

# var_5pc_2016_bond_etf = cav_simul(c("SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2012-01-01", end_date = "2016-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/", filename = "var_5pc_2016_bond_etf.csv", uv_list = var_5pc_2016_usetf[[1]])

# var_10pc_2016_bond_etf = cav_simul(c("SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2012-01-01", end_date = "2016-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/", filename = "var_10pc_2016_bond_etf.csv", uv_list = var_10pc_2016_usetf[[1]])
# Call the above function
v1_2016_alletf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/","var_1pc_2016_all_etf.csv", 0.01)
v5_2016_alletf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/","var_5pc_2016_all_etf.csv", 0.05)
v10_2016_alletf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/","var_10pc_2016_all_etf.csv", 0.10)
# 1%, 5%, 10% VaR - 2016 - 5th set of predictors
# var_1pc_2016_all_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE", "JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC", "SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2012-01-01", end_date = "2016-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 23, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/", filename = "var_1pc_2016_all_etf.csv", uv_list = var_1pc_2016_usetf[[1]])

# var_5pc_2016_all_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE", "JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC", "SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2012-01-01", end_date = "2016-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 23, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/", filename = "var_5pc_2016_all_etf.csv", uv_list = var_5pc_2016_usetf[[1]])

# var_10pc_2016_all_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE", "JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC", "SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2012-01-01", end_date = "2016-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 23, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/", filename = "var_10pc_2016_all_etf.csv", uv_list = var_10pc_2016_usetf[[1]])

Literature Cited

LS0tCnRpdGxlOiAiTXVsdGl2YXJpYXRlIENBVmlhUiIKc3VidGl0bGU6ICJBbiBJbnNpZ2h0ZnVsIEFwcHJvYWNoIHRvIFJpc2sgTW9kZWxpbmciCmF1dGhvcjogIlN0ZXZlbiBNb2VuIgpkYXRlOiAiU3VuZGF5LCBNYXkgM3JkLCAyMDIwIgpvdXRwdXQ6CiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0CiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdAotLS0KCmBgYHtyIGdsb2JhbF9vcHRpb25zLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0PTgsIGZpZy5wYXRoPSdGaWdzLycsCiAgICAgICAgICAgICAgICAgICAgICBlY2hvPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBjYWNoZSA9IFRSVUUpCmBgYAoKIyBBYnN0cmFjdAoKVGhpcyB0aGVzaXMgYnVpbGRzIHVwb24gcHJldmlvdXMgbGl0ZXJhdHVyZSBmb3IgbW9kZWxpbmcgdmFsdWUtYXQtcmlzayAoZGVmaW5lZCBhcyBhbiB4JSBxdWFudGlsZSBvZiBhbiBhc3NldCdzIGRhaWx5IHJldHVybnMpIHVzaW5nIG5vbi1saW5lYXIgQVJNQSB0ZXJtcyBieSBhZGRpbmcgZXhjaGFuZ2UtdHJhZGVkIGZ1bmRzIChFVEZzKSBhcyBleHBsYW5hdG9yeSB2YXJpYWJsZXMgdGhhdCBhcmUgY29tYmluZWQgaW50byBwcmluY2lwYWwgY29tcG9uZW50IHZlY3RvcnMgYXQgdGhlIGZvcmVjYXN0IG9yaWdpbi4gQ29tYmluaW5nIHRoZXNlIHByaW5jaXBhbCBjb21wb25lbnQgdmVjdG9ycyB3aXRoIHRyYW5zZm9ybWF0aW9ucyBvZiBsYWdnZWQgYXV0b3JlZ3Jlc3NpdmUgcmVzcG9uc2UgdmFyaWFibGVzIHJlc3VsdHMgaW4gYSBtb2RlbCB0aGF0IHByb2R1Y2VzIHNpbWlsYXIgcHJlZGljdGl2ZSBhY2N1cmFjeSBkdXJpbmcgcGVyaW9kcyBvZiByZWxhdGl2ZWx5IGxvdyB2b2xhdGlsaXR5IGFsb25nIHdpdGggbW9yZSBpbnNpZ2h0IGludG8gdGhlIGRyaXZlcnMgb2YgdGhlIGNoYW5nZXMgaW4gdGhlIHJlc3BvbnNlIHZhcmlhYmxlLiBJbiBmYWN0LCBvbmUgaW5zaWdodCBnYWluZWQgZnJvbSB0aGUgbmV3IG1vZGVsIGlzIGEgbWV0aG9kIG9mIGRldGVjdGluZyBjaGFuZ2Vwb2ludHMgaW4gdGhlIGVjb25vbXkgYnkgbWVhc3VyaW5nIHRoZSBhbmdsZSBiZXR3ZWVuIHJlc3VsdGFudCB2ZWN0b3JzIGNhbGN1bGF0ZWQgZnJvbSB0aGUgY29tYmluYXRpb24gb2YgcHJpbmNpcGFsIGNvbXBvbmVudCB2ZWN0b3JzIGR1cmluZyBkaWZmZXJlbnQgdGltZSBwZXJpb2RzLiBUaGlzIG1ldGhvZCwgYWxvbmcgd2l0aCBhbmFseXNpcyBvZiB0aGUgc3RhdGlzdGljYWwgc2lnbmlmaWNhbmNlIG9mIHRoZSBsYWdnZWQgRVRGcywgYWxsb3dzIGZvciBpbnNpZ2h0IGludG8gY2hhbmdlcyBpbiB0aGUgdW5kZXJseWluZyBlY29ub215LgoKIyBCYWNrZ3JvdW5kIGFuZCBJbnRyb2R1Y3Rpb24KCldoZW4gbW9kZWxpbmcgZmluYW5jaWFsIHRpbWUgc2VyaWVzLCBzaW1wbHkgY29uc2lkZXJpbmcgdGhlIG1lYW4gYW5kIHRoZSB2YXJpYW5jZSBpcyBpbnN1ZmZpY2llbnQuIEluIGZhY3QsIG1vZGVsaW5nIGEgMSUgb3IgYSA1JSBxdWFudGlsZSBvZiBkYWlseSByZXR1cm5zIGlzIGEgd2F5IHRvIHVuZGVyc3RhbmQgd2hhdCBoYXBwZW5zIG9uIHRoZSB3b3JzdCBkYXlzIGFuZCB0byBoYXZlIGEgY2xlYXJlciBwaWN0dXJlIG9mIHdoYXQgbWlnaHQgaGFwcGVuIGR1cmluZyBhIGRvd250dXJuLiBJbmRlZWQsIGZpbmFuY2UgdGhlb3J5IHN1Z2dlc3RzIHRoYXQgYSBwcmltYXJ5IHJlYXNvbiB3aHkgdGhlIFMmUCA1MDAsIHdoaWNoIGlzIGEgbWFya2V0LWNhcGl0YWxpemF0aW9uIHdlaWdodGVkIGluZGV4IGNvbXBvc2VkIG9mIHRoZSA1MDAtbGFyZ2VzdCBwdWJsaWNseSB0cmFkZWQgY29tcGFuaWVzIGluIHRoZSBVbml0ZWQgU3RhdGVzLCBoYXMgZWFybmVkIDYuOCUgaW5mbGF0aW9uLWFkanVzdGVkIHByZS10YXggcmV0dXJuIHdpdGggZGl2aWRlbmQgcmVpbnZlc3RtZW50IGZyb20gSmFudWFyeSAxODcxIHRocm91Z2ggQXByaWwgMjAyMCAoQ0lURSkgaXMgYmVjYXVzZSBvZiB0aGUgcmlzayBvZiBhIHNpZ25pZmljYW50IGRvd250dXJuLiBLZXJyeSBQZWNodGVyIGF0IEZvcmJlcyBkZXNjcmliZXMgaXQgYXMgYSBwcmVtaXVtIGZvciB0aGUgZmFjdCB0aGF0ICJzdG9ja3MgYXJlIHJpc2tpZXIiIGFuZCAibW9yZSBwcm9uZSB0byBwcmljZSBmbHVjdHVhdGlvbnMgaW4gdGhlIHNob3J0IHJ1biIgY29tcGFyZWQgdG8gbG93ZXIgcmlzayBpbnZlc3RtZW50cyAoQ0lURSkuIFdoaWxlIHRoZSBsb25nLXJ1biBwaWN0dXJlIG9mIHN0b2NrIHJldHVybnMgaXMgYSBiaXQgY2xlYXJlciwgdGhlIHNob3J0LXJ1biBpcyBhIGh1Z2UgcXVlc3Rpb24gLSBhbiBpbnZlc3RtZW50IG1hbmFnZXIgdXNpbmcgZmluYW5jaWFsIGxldmVyYWdlIHRvIG1hZ25pZnkgcmV0dXJucyAocG9zaXRpdmUgb3IgbmVnYXRpdmUpIHRoYXQgY291bGQgbGVhdmUgdGhlbSBpbiBkaXJlIHN0cmFpdHMgaWYgdGhlaXIgaW52ZXN0bWVudHMgZmVsbCByYXBpZGx5LCBkZXNwaXRlIGEgc291bmQgbG9uZy1ydW4gc3RyYXRlZ3kuCgpXaGlsZSB0aGVyZSBhcmUgb3RoZXIgd2F5cyB0byB1bmRlcnN0YW5kIGFuZCBtZWFzdXJlIGRvd25zaWRlIHJpc2ssIGEgY29tbW9ubHkgYWNjZXB0ZWQgbWVhbnMgaXMgdXNpbmcgdmFsdWUtYXQtcmlzayAoVmFSKS4gVGhlIG1ldHJpYyBpcyB1bmRlcnN0b29kIGFzIGZvbGxvd3M6IGEgb25lLWRheSAxJSBWYVIgb2YgLTEwJSBmb3IgYSBwb3J0Zm9saW8gbWVhbnMgdGhhdCB0aGUgcG9ydGZvbGlvIHdpbGwgbG9zZSBhdCBsZWFzdCAxMCUgb2YgaXRzJyB2YWx1ZSBvbiB0aGUgMSUgd29yc3QgdHJhZGluZyBkYXlzLiBBIG1ham9yIGFkdmFudGFnZSBvZiBWYVIgaXMgdGhhdCBpdCBkaXN0aWxscyBhIGRpc3RyaWJ1dGlvbiBvZiByZXR1cm5zIGludG8gb25lIG51bWJlci4gQXMgc3VjaCwgVmFSIGlzIG9mdGVuIHVzZWQgaW4gc3RyZXNzIHRlc3RpbmcgYnkgcmVndWxhdG9yeSBhZ2VuY2llcyBpbiB0aGUgVW5pdGVkIFN0YXRlcywgdGhlIFVuaXRlZCBLaW5nZG9tLCBhbmQgRXVyb3BlIChDSVRFKS4KCk1hbnkgb2YgdGhlIGFwcHJvYWNoZXMgZm9yIG1vZGVsaW5nIFZhUiByZWx5IG9uIGEgc2VtaXBhcmFtZXRyaWMgb3IgYSBub25wYXJhbWV0cmljIGhpc3RvcmljYWwgc2ltdWxhdGlvbiAoQUREIENJVEFUSU9OIC0gQk9VRE9VS0gpLiBBY2NvcmRpbmcgdG8gUm9iZXJ0IEVuZ2xlIGFuZCBTaW1vbmUgTWFuZ2FuZWxsaSBpbiBhIDIwMDQgcGFwZXIsIHRoZXNlIG1ldGhvZHMgYXJlIHVzdWFsbHkgY2hvc2VuIGZvciDigJxlbXBpcmljYWwganVzdGlmaWNhdGlvbnMgcmF0aGVyIHRoYW4gb24gc291bmQgc3RhdGlzdGljYWwgdGhlb3J54oCdIChBREQgQ0lUQVRJT04gLSBFTkdMRSkuIEFzIHN1Y2gsIHRoZXkgcHJvcG9zZSBhIGZyYW1ld29yayBjYWxsZWQgQ0FWaWFSIHRoYXQgZm9yZWNhc3RzIHRoZSBWYVIgcXVhbnRpbGUgZGlyZWN0bHkgdXNpbmcgYSBjb25kaXRpb25hbCBhdXRvcmVncmVzc2l2ZSBxdWFudGlsZSBzcGVjaWZpY2F0aW9uLiBUaGlzIGFwcHJvYWNoIGJ1aWxkcyB1cG9uIHRoZSBzdGF0aXN0aWNhbCBsaXRlcmF0dXJlIHRoYXQgZXh0ZW5kcyBsaW5lYXIgcXVhbnRpbGUgbW9kZWxzIHRvIHNldHRpbmdzIGFtZW5hYmxlIHRvIGZpbmFuY2lhbCBtb2RlbGluZywgc3VjaCBhcyB3aXRoIGhldGVyb3NrZWRhc3RpYyBhbmQgbm9uc3RhdGlvbmFyeSBlcnJvciBkaXN0cmlidXRpb25zIChBREQgQ0lUQVRJT04gLSBLT0VOS0VSLCBQT1JUTk9ZKS4KCiMgTWV0aG9kcyBVc2VkCgpBIGNvbW1vbiBwcm9ibGVtIGluIHN0YXRpc3RpY2FsIGFuYWx5c2lzIG9jY3VycyB3aGVuIGEgdHJhaW5pbmcgc2FtcGxlIGlzIHNpZ25pZmljYW50bHkgZGlmZmVyZW50IHRoYW4gdGhhdCBvZiB0aGUgdGVzdCBzYW1wbGUuIEluaXRpYWwgbW90aXZhdGlvbnMgZm9yIHRoaXMgcGFwZXIgaW52b2x2ZWQgYW5hbHl6aW5nIHR3byBzdG9ja3MgLSBBbWF6b24gKHRpY2tlcjogQU1aTikgYW5kIFByb2N0b3IgJiBHYW1ibGUgKHRpY2tlcjogUEcpIGFuZCB0aGVpciBwZXJmb3JtYW5jZSBkdXJpbmcgdGhlIGdyZWF0IHJlY2Vzc2lvbi4gQSByZWxldmFudCBxdWVzdGlvbiBvZiBhIGZpbmFuY2lhbCBpbnN0aXR1dGlvbiB3b3VsZCB1bmRlcnN0YW5kYWJseSBiZSBob3cgdGhlaXIgcmlzayBtb2RlbCBwZXJmb3JtZWQgZHVyaW5nIDIwMDgsIGEgaGlnaGx5IHZvbGF0aWxlIHBlcmlvZCB3aGljaCB3YXMgZHJpdmVuIGJ5IHRoZSAid29yc3QgZmluYW5jaWFsIGNyaXNpcyBzaW5jZSB0aGUgR3JlYXQgRGVwcmVzc2lvbiIgYWNjb3JkaW5nIHRvIEdhcnkgQmVja2VyIChDSVRFKSwgYSBOb2JlbC1wcml6ZSB3aW5uaW5nIEVjb25vbWlzdC4gSW50ZXJlc3RpbmdseSwgdGhlIGZvcmVjYXN0IGZvciBBbWF6b24gd2FzIGZhaXJseSBhY2N1cmF0ZSB3aGVyZWFzIHRoZSBmb3JlY2FzdCBmb3IgUEcgd2FzIG5vdC4gT25lIHJlYXNvbiBmb3IgdGhpcyBjb3VsZCBiZSB0aGUgZmFjdCB0aGF0IGEgc3RvY2sgbGlrZSBBbWF6b24gd2FzIGhpZ2hseSB2b2xhdGlsZSBkdXJpbmcgdGhlIHRyYWluaW5nIHNhbXBsZSwgd2hpY2ggaW5jbHVkZWQgZGF0YSBmcm9tIHByZXZpb3VzIHllYXJzIChIT1cgTUFOWT8pLCBidXQgUEcgd2FzIGZhaXJseSBjYWxtLiBIb3cgd291bGQgaXQgYmUgcG9zc2libGUgZm9yIGEgdW5pdmFyaWF0ZSBtb2RlbCBzdWNoIGFzIENBVmlhUiwgdGhhdCBkb2VzIG5vdCBleHBsaWNpdGx5IGFjY291bnQgZm9yIG90aGVyIGZhY3RvcnMsIHRvIGZvcmVjYXN0IHdlbGw/IFdoYXQgaWYgYSB2b2xhdGlsZSBzdG9jayBzdWNoIGFzIEFNWk4gd2FzIGluY2x1ZGVkIGludG8gdGhlIGZvcmVjYXN0IGZvciBQRyAtIHdvdWxkIGl0IGltcHJvdmUgdGhlIGZvcmVjYXN0PwoKVGh1cywgdGhlIGlkZWEgb2YgY29tYmluaW5nIHN0b2NrcyBpbnRvIGEgbXVsdGl2YXJpYXRlIHNldHRpbmcgdG8gY2FwdHVyZSBjb3JyZWxhdGlvbnMgYW5kIGJldHRlciBmb3JlY2FzdCByaXNrIHdhcyBmb3JtZWQuIEEgbmF0dXJhbCBjaG9pY2UgYXBwZWFyZWQgdG8gYmUgdGhlIGRpZmZ1c2lvbiBpbmRleCBtb2RlbCwgb3JpZ2luYWxseSBkZXZlbG9wZWQgYnkgU3RvY2sgYW5kIFdhdHNvbiBmb3IgcHJlZGljdGluZyBjb25kaXRpb25hbCBtZWFucyBbVFdPIENJVEFUSU9OU10uIFRoZSBtb2RlbCBmb3IgZm9yZWNhc3RpbmcgdGhlIGNvbmRpdGlvbmFsIG1lYW4gaXMgc3BlY2lmaWVkIGJlbG93LgoKIyMgRGlmZnVzaW9uIEluZGV4IE1vZGVsCgpBIHVzZWZ1bCBtZWFucyBvZiBwcmVkaWN0aW5nIHN0b2NrIG1vdmVtZW50cyBpbiB0aGUgZnV0dXJlIGlzIHRoZSBTdG9jayBhbmQgV2F0c29uIGRpZmZ1c2lvbiBpbmRleC4gVGhlIG1vZGVsIGlzIG91dGxpbmVkIGJlbG93LCB3aGljaCBpcyBhZGFwdGVkIGZyb20gTXVsdGl2YXJpYXRlIFRpbWUgU2VyaWVzIEFuYWx5c2lzIFdpdGggUiBhbmQgRmluYW5jaWFsIEFwcGxpY2F0aW9ucyBieSBSdWV5IFMuIFRzYXkgW0FERCBDSVRBVElPTl0uCgpUaGVyZSBhcmUgdHdvIHJlbGV2YW50IGVxdWF0aW9uczoKCiQkClxib2xkc3ltYm9se3pfdH0gPSBcYm9sZHN5bWJvbHtMZl90fSArIFxib2xkc3ltYm9se1xlcHNpbG9uX3R9CiQkCgphbmQgCgokJAp5X3t0K2h9ID0gXGJvbGRzeW1ib2x7XGJldGFeXHByaW1lIGZfdH0gKyBcYm9sZHN5bWJvbHtlX3t0K2h9fQokJAoKSW4gdGhlIGZpcnN0IGVxdWF0aW9uICRcYm9sZHN5bWJvbHt6X3R9ID0gKHpfezF0fSwgLi4uLiwgel97a3R9KV5ccHJpbWUkIGlzIGFuIG9ic2VydmVkIHRpbWUgc2VyaWVzIHdpdGggbWVhbiAwLCAkXGJvbGRzeW1ib2x7Zl90fSQgaXMgYW4gbS1kaW1lbnNpb25hbCB2ZWN0b3Igb2YgY29tbW9uIGZhY3RvcnMgd2l0aCBtZWFuIDAgYW5kIGlkZW50aXR5IGNvdmFyaWFuY2UgbWF0cml4LCAkXGJvbGRzeW1ib2x7TH0kIGlzIGEgJGskIHggJG0kIGxvYWRpbmcgbWF0cml4LCBhbmQgJFxib2xkc3ltYm9se1xlcHNpbG9uX3R9JCBpcyBhIGkuaS5kLiBzZXF1ZW5jZSBvZiByYW5kb20gdmVjdG9ycyB3aXRoIG1lYW4gMCBhbmQgY292YXJpYW5jZSBtYXRyaXggJFxib2xkc3ltYm9se1xTaWdtYV9lfSQuCgpJbiB0aGUgc2Vjb25kIGVxdWF0aW9uLCB3aGljaCByZXByZXNlbnRzIHRoZSBoLXN0ZXAgYWhlYWQgcHJlZGljdGlvbiBiYXNlZCBvbiAkXGJvbGRzeW1ib2x7Zl90fSQsICR5X3QkIGlzIHRoZSBzY2FsYXIgdGltZSBzZXJpZXMgb2YgaW50ZXJlc3QsICRoJCBpcyB0aGUgZm9yZWNhc3QgaG9yaXpvbiwgJFxib2xkc3ltYm9se1xiZXRhfSQgcmVwcmVzZW50cyB0aGUgdmVjdG9yIG9mIGNvZWZmaWNpZW50cywgYW5kICRlX3QkIGlzIGEgc2VxdWVuY2Ugb2YgdW5jb3JyZWxhdGVkIHJhbmRvbSB2YXJpYWJsZXMgd2l0aCBtZWFuIDAgYW5kIGNvbnN0YW50IHZhcmlhbmNlLiAKClRvIG1vZGVsIHRoZSBkYXRhLCBwcmluY2lwYWwgY29tcG9uZW50IGFuYWx5c2lzIGlzIHBlcmZvcm1lZCBvbiB0aGUgY292YXJpYXRlcyBkZXNjcmliZWQgYmVsb3cgdG8gb2J0YWluIGFuIGVzdGltYXRlIG9mICRcYm9sZHN5bWJvbHtmX3R9JC4gVGhlbiB0aGUgJFxib2xkc3ltYm9se1xiZXRhfSQgY29lZmZpY2llbnRzIGFyZSBlc3RpbWF0ZWQgdXNpbmcgb3JkaW5hcnkgbGVhc3Qgc3F1YXJlcy4KCiMjIFVuaXZhcmlhdGUgQ0FWaWFSIE1vZGVsCgpIb3dldmVyLCB3b3JrIG5lZWRlZCB0byBiZSBkb25lIHRvIGFsaWduIHRoZSBkaWZmdXNpb24gaW5kZXggbW9kZWwgd2l0aCB0aGUgQ0FWaWFSIG1vZGVsLCB3aGljaCBpcyBkZWZpbmVkIGJlbG93LiBUaGUgZm9sbG93aW5nIHZhcmlhYmxlcyBhcmUgcmVxdWlyZWQgZm9yIHVzZSBpbiB0aGUgQ0FWaWFSIG1vZGVsOgoKW0RFU0NSSVBUSU9OIE9GIFZBUklBQkxFU10KCiMjIyBBZGFwdGl2ZSBDQVZpYVIgTW9kZWwKCiQkCmZfdChcYmV0YV8xKSA9IGZfe3QtMX0oXGJldGFfMSkgKyBcYmV0YV8xXGxlZnRbXGxlZnQoMSsgXGV4cChHW3lfe3QtMX0gLSBmX3t0LTF9KFxiZXRhXzEpXSkgIFxyaWdodCleey0xfSAtIFx0aGV0YSBccmlnaHRdIAokJAoKIyMjIFN5bW1ldHJpYyBBYnNvbHV0ZSBWYWx1ZSBDQVZpYVIgTW9kZWwKCiQkCmZfdChcYm9sZHN5bWJvbHtcYmV0YX0pID0gXGJldGFfMSArIFxiZXRhXzJmX3t0LTF9KFxib2xkc3ltYm9se1xiZXRhfSkgKyBcYmV0YV8zfHlfe3QtMX18CiQkCgojIyMgQXN5bW1ldHJpYyBTbG9wZSBDQVZpYVIgTW9kZWwKCiQkCmZfdChcYm9sZHN5bWJvbHtcYmV0YX0pID0gXGJldGFfMSArIFxiZXRhXzJmX3t0LTF9KFxib2xkc3ltYm9se1xiZXRhfSkgKyBcYmV0YV8zKHlfe3QtMX0pXisgKyBcYmV0YV80KHlfe3QtMX0pXi0KJCQKCiMjIyBJbmRpcmVjdCBHQVJDSCAoMSwxKSBDQVZpYVIgTW9kZWwKCiQkCmZfdChcYm9sZHN5bWJvbHtcYmV0YX0pID0gKFxiZXRhXzEgKyBcYmV0YV8yZl97dC0xfV4yKFxib2xkc3ltYm9se1xiZXRhfSkgKyBcYmV0YV8zeV97dC0xfV4yKV57MS8yfQokJAoKIyMgTXVsdGl2YXJpYXRlIENBVmlhUiBNb2RlbAoKVGhlIG11bHRpdmFyaWF0ZSBDQVZpYVIgbW9kZWwgdGFrZXMgaW5zcGlyYXRpb24gZnJvbSB0aGUgbW9kZWxzIGRlc2NyaWJlZCBhYm92ZSBpbiBzZXZlcmFsIHNwZWNpZmljYXRpb25zLiBUaGUgZ2VuZXJhbCBtb2RlbCBmb3JtIGxvb2tzIGxpa2UgdGhlIHNwZWNpZmljYXRpb24gYmVsb3cuCgpWQVIgPSBJTlRFUkNFUFQgKyBQQVNUIFZBTFVFUyArIEFSIENPTVBPTkVOVCArIEVSUk9SCgojIyMgTXVsdGl2YXJpYXRlIENBVmlhUjogTm8gTGFncyBNb2RlbAoKVkFSID0gSU5URVJDRVBUICsgUEFTVCBWQUxVRVMgKyBFUlJPUgoKIyMjIE11bHRpdmFyaWF0ZSBDQVZpYVIgd2l0aCBBdXRvcmVncmVzc2l2ZSBUZXJtcyBBZGRlZAoKVkFSID0gSU5URVJDRVBUICsgUEFTVCBWQUxVRVMgKyBBUiBDT01QT05FTlQgKyBFUlJPUgoKIyMjIE11bHRpdmFyaWF0ZSBDQVZpYVIgd2l0aCBTeW1tZXRyaWMgQWJzb2x1dGUgVmFsdWUgQXV0b3JlZ3Jlc3NpdmUgVGVybXMgQWRkZWQKClZBUiA9IElOVEVSQ0VQVCArIFBBU1QgVkFMVUVTICsgU0FWIEFSIENPTVBPTkVOVCArIEVSUk9SCgojIyMgTXVsdGl2YXJpYXRlIENBVmlhUiB3aXRoIEFzeW1tZXRyaWMgU2xvcGUgQXV0b3JlZ3Jlc3NpdmUgVGVybXMgQWRkZWQKClZBUiA9IElOVEVSQ0VQVCArIFBBU1QgVkFMVUVTICsgQVMgQVIgQ09NUE9ORU5UICsgRVJST1IKCgojIyBGaXR0aW5nIHRoZSBNb2RlbHMKClRvIGZpdCB0aGUgbW9kZWxzLCBhbiBvcHRpbWFsIHZhbHVlIG9mICRtJCBkaWZmdXNpb24gaW5kaWNlcyBhbmQgJHAkIGF1dG9yZWdyZXNzaXZlIHRlcm1zIGFyZSBhZGRlZCAob3IgJDJwJCBpbiB0aGUgY2FzZSBvZiB0aGUgYXN5bW1ldHJpYyBzbG9wZSBtb2RlbCkuIFRoZSBvcHRpbWFsIHZhbHVlcyBvZiB0aGVzZSBwYXJhbWV0ZXJzIGFyZSBhcnJpdmVkIGF0IHVzaW5nIGEgdmFsaWRhdGlvbiBkYXRhc2V0LiBJbiBhbGwgb2YgdGhlIHJ1bnMgYmVsb3csIHRoZXJlIGFyZSBhIHRvdGFsIG9mIDUgeWVhcnMgb2YgdHJhZGluZyBkYXlzLCBvciBhYm91dCAxLDI2MCBkYXlzIGFzc3VtaW5nIDI1MiB0cmFkaW5nIGRheXMgYSB5ZWFyLiBUaGUgYWRqdXN0ZWQgY2xvc2luZyBwcmljZXMgYXJlIGxvZ2dlZCBhbmQgZGlmZmVyZW5jZWQsIHNob3J0ZW5pbmcgdGhlIGRhdGFzZXQgYnkgb25lLiBBZnRlciBkb2luZyB0aGlzLCB0aGUgbGFzdCAyNTAgZGF0YSBwb2ludHMgYXJlIHJlc2VydmVkIGFzIHRlc3QgZGF0YSwgYW5kIHRoZSAyNTAgZGF0YSBwb2ludHMgYmVmb3JlIHRoYXQgYXJlIHVzZWQgYXMgYSB2YWxpZGF0aW9uIHNldC4gTWVhc3VyZWQgYnkgdGhlIGxvc3MgZnVuY3Rpb24gd3JpdHRlbiBvdXQgYmVsb3csIHRoZSB2YWx1ZXMgb2YgJHAkIGFuZCAkbSQgdGhhdCBtaW5pbWl6ZSBsb3NzZXMgYXJlIGNob3NlbiBhbmQgdGhlIG9wdGltYWwgbW9kZWwgaXMgcmVmaXQgb3ZlciBib3RoIHRoZSB0cmFpbmluZyBhbmQgdGhlIHZhbGlkYXRpb24gZGF0YSBjb21iaW5lZCBhbmQgdGhlbiBldmFsdWF0ZWQgb24gdGhlIHRlc3QgZGF0YS4gTm90ZSB0aGF0IHRoaXMgYW4gb3B0aW1hbCBtb2RlbCBpcyBjaG9zZW4gZm9yIGVhY2ggb2YgdGhlIGZvdXIgbXVsdGl2YXJpYXRlIENBVmlhUiBzcGVjaWZpY2F0aW9ucyBkZXNjcmliZWQgYWJvdmUsIHNvIHRoZXJlIGFyZSA0IG9wdGltYWwgc2V0cyBvZiAkcCQgYW5kICRtJCBjaG9zZW4gZm9yIGVhY2ggc2V0IG9mIG1vZGVsLiBUaHVzLCB0aGVyZSBhcmUgOCBtb2RlbHMgY29tcGFyZWQgb24gdGhlIHRlc3QgZGF0YSAtIDQgdW5pdmFyaWF0ZSBDQVZpYVIgbW9kZWxzIGFuZCA0IG11bHRpdmFyaWF0ZSBDQVZpYVIgbW9kZWxzLgoKW0xPU1MgRlVOQ1RJT05dCgojIERhdGEgVXNlZAoKVGhlIHJlc3BvbnNlIHZhcmlhYmxlIHVzZWQgaW4gdGhpcyBhbmFseXNpcyBpcyBTUFksIHdoaWNoIGlzIGFuIGV4Y2hhbmdlLXRyYWRlZCBmdW5kIHRoYXQgYWltcyB0byB0cmFjayB0aGUgcGVyZm9ybWFuY2Ugb2YgdGhlIFMmUCA1MDAsIHdoaWNoIGlzIGRpc2N1c3NlZCBhYm92ZS4gSXQgaXMgYnJvYWRseSB1c2VkIGFzIGEgYmVsbHdldGhlciBvZiB0aGUgVS5TLiBlY29ub215IChDSVRFKSwgYW5kIGhhcyB0aGUgYWR2YW50YWdlIG9mIGF2b2lkaW5nIHN1cnZpdm9yc2hpcCBiaWFzIC0gd2hpbGUgYW4gaW5kaXZpZHVhbCBzdG9jayBtaWdodCBnbyBiYW5rcnVwdCBvciBtZXJnZSB3aXRoIGFub3RoZXIsIGl0J3MgcmVhc29uYWJsZSB0byBhc3N1bWUgdGhhdCB0aGVzZSBpc3N1ZXMgZG8gbm90IGFwcGx5IHdpdGggYW4gRVRGLiAKCkZvbGxvd2luZyB0aGlzIGxvZ2ljLCB0aGVyZSBhcmUgc2V2ZXJhbCBjbGFzc2VzIG9mIHJlc3BvbnNlIHZhcmlhYmxlcyB1c2VkIGluIHRoaXMgYW5hbHlzaXMuIFRoZSBmaXJzdCBncm91cCBpcyBhIHNldCBvZiBVLlMuIHNlY3RvciBFVEZzIG9idGFpbmVkIGZyb20gU2Vla2luZyBBbHBoYSBbQ0lURV0gdXNpbmcgdGhlIGxpbmsgYmVsb3cuIEFzIHdpdGggdGhlIHJlc3BvbnNlIHZhcmlhYmxlLCB0aGVzZSBFVEZzIHdlcmUgcHVibGljbHkgdHJhZGVkIHRocm91Z2hvdXQgdGhlIEdyZWF0IFJlY2Vzc2lvbi4KCmEuIFV0aWxpdGllcyAoWExVKQpiLiBDb25zdW1lciBTdGFwbGVzIChYTFApCmMuIEhlYWx0aGNhcmUgKFhMVikKZC4gVGVjaG5vbG9neSAoWExLKQplLiBDb25zdW1lciBEaXNjcmV0aW9uYXJ5IChYTFkpCmYuIEluZHVzdHJpYWwgKFhMSSkKZy4gRmluYW5jaWFsIFNlcnZpY2VzIChYTEYpCmguIEJhc2ljIE1hdGVyaWFscyAoWExCKQppLiBFbmVyZ3kgKFhMRSkKClRoZSBzZWNvbmQgaXMgR2xvYmFsIFNlY3RvciBFVEZzLCBhbHNvIG9idGFpbmVkIGZyb20gU2Vla2luZyBBbHBoYS4gVGhlIHJhdGlvbmFsZSBmb3IgaW5jbHVkaW5nIHRoZXNlIGlzIHRoYXQgcGVyaGFwcyBzb21lIGdsb2JhbCBleHBvc3VyZSBpcyB1c2VmdWwgaW4gdW5kZXJzdGFuZGluZyB0aGUgYnJvYWRlciBtYXJrZXQuCgphLiBVdGlsaXRpZXMgKEpYSSkKYi4gQ29uc3VtZXIgU3RhcGxlcyAoS1hJKQpjLiBIZWFsdGhjYXJlIChJWEopCmQuIFRlbGVjb21tdW5pY2F0aW9ucyAoSVhQKQplLiBUZWNobm9sb2d5IChJWE4pCmYuIENvbnN1bWVyIERpc2NyZXRpb25hcnkgKFJYSSkKZy4gSW5kdXN0cmlhbCAoRVhJKQpoLiBGaW5hbmNpYWwgU2VydmljZXMgKElYRykKaS4gQmFzaWMgTWF0ZXJpYWxzIChNWEkpCmouIEVuZXJneSAoSVhDKQoKVGhlIHRoaXJkIGlzIGJvbmQgRVRGcywgYWxzbyBvYnRhaW5lZCBmcm9tIFtDSVRFXS4gTGlrZSB0aGUgcHJldmlvdXMgdHdvLCB0aGVzZSBFVEZzIHBvdGVudGlhbGx5IGNvbnRhaW4gZm9yd2FyZC1sb29raW5nIGluZm9ybWF0aW9uIGFib3V0IHRoZSBzdG9jayBtYXJrZXQuIExpbmsgYmVsb3c6CgphLiBpU2hhcmVzIDEtMyBZZWFyIFRyZWFzdXJ5IEJvbmQgRnVuZCAoU0hZKQpiLiBpU2hhcmVzIDctMTAgWWVhciBUcmVhc3VyeSBCb25kIEZ1bmQgKElFRikKYy4gaVNoYXJlcyAyMCsgWWVhciBUcmVhc3VyeSBCb25kIEZ1bmQgKFRMVCkKZC4gaVNoYXJlcyBpQm94eCAkIEludmVzdG1lbnQgR3JhZGUgQ29ycG9yYXRlIEJvbmQgRVRGIChMUUQpCgpMYXN0bHksIGFsbCBvZiB0aGUgYWJvdmUgYXJlIHJ1biB0b2dldGhlci4gSW4gZWFjaCBydW4sIHRoZSBleHBsYW5hdG9yeSB2YXJpYWJsZXMgYXJlIGxhZ2dlZCB0byBhdm9pZCBsb29rLWFoZWFkIGJpYXMuIEFsbCBvZiB0aGUgcnVucyBhbmFseXplIHRoZSBkaWZmZXJlbmNlIG9mIHRoZSBsb2cgb2YgdGhlIGFkanVzdGVkIGNsb3NpbmcgcHJpY2UuIFRoZSByZWFzb24gZm9yIHVzaW5nIHRoZSBkaWZmZXJlbmNlZCBsb2cgaXMgdGhhdCBpdCBjbG9zZWx5IGFwcHJveGltYXRlcyB0aGUgcGVyY2VudGFnZSBjaGFuZ2Ugb2YgdGhlIHByaWNlIGZvciBzbWFsbCBjaGFuZ2VzLiBBbHNvLCAKCiMgUmVzdWx0cwoKYGBge3J9CiMgUmVhZCBpbiByZWxldmFudCBsaWJyYXJpZXMKbGlicmFyeShtaWNyb2JlbmNobWFyaykKbGlicmFyeShkYXRhLnRhYmxlKQpsaWJyYXJ5KHF1YW50bW9kKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkodHNlcmllcykKbGlicmFyeSh6b28pCmxpYnJhcnkobWFncml0dHIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoa2FibGVFeHRyYSkKbGlicmFyeShmb3JtYXR0YWJsZSkKbGlicmFyeShxdWFudHJlZykKbGlicmFyeShNVFMpCmxpYnJhcnkocGxvdDNEKQpsaWJyYXJ5KGNpdHIpCmxpYnJhcnkoZm9ybWF0dGFibGUpCgojIFNldCB1cCB3b3JraW5nIGRpcmVjdG9yeQojIHNldHdkKCJ+L0RvY3VtZW50cy9HaXRIdWIvQ2F2aWFSIikKCiMgc291cmNlKCdjYXZpYXJfU00uUicpCnNvdXJjZSgnfi9Eb2N1bWVudHMvR2l0SHViL0NhdmlhUi9jYXZpYXJfU00uUicpCmBgYAoKYGBge3J9CiMgVGhpcyBjb2RlIGJlbG93IGlzIGZvciB1c2UgaW4gdGhlIENBVmlhUiBzZWN0aW9ucy4KYGBgCgpgYGB7cn0KIyBIZXJlIGlzIGNvZGUgdGhhdCBJJ2xsIHdyYXAgc29tZSBwYXJ0cyBpbiB0byBhdm9pZCBzdXBlcmZsdW91cyBvdXRwdXQKcXVpZXQgPC0gZnVuY3Rpb24oeCkgeyAKICBzaW5rKHRlbXBmaWxlKCkpIAogIG9uLmV4aXQoc2luaygpKSAKICBpbnZpc2libGUoZm9yY2UoeCkpIAp9IApgYGAKCgpgYGB7cn0KIycgVGhpcyBpcyBhIGZ1bmN0aW9uIHdoaWNoIHB1bGxzIGRhdGEgZm9yIHVzZSBpbiB0aGUgQ0FWaWFSIG1vZGVsCiMnCiMnIEBwYXJhbSBzeW1ib2wgLSBzeW1ib2wgdG8gcHVsbAojJyBAcGFyYW0gY29tcGxfY2FzZSAtIGRlZmF1bHRzIHRvIHRydWUuLi5vbmx5IGluY2x1ZGVzIGNvbXBsZXRlIGNhc2VzIGluIHRoZSBkYXRhCiMnIEBwYXJhbSBhZGpfY2xvc2UgLSB1c2UgYWRqdXN0ZWQgY2xvc2luZyBwcmljZXMuIERlZmF1bHQgaXMgeWVzLgojJyBAcGFyYW0gbG9nX3JldHVybiAtIHVzZSBsb2cgcmV0dXJuPyBEZWZhdWx0IGlzIHllcy4KIycKIycgQHJldHVybiAtIGEgZGF0YSBmcmFtZSB3aGljaCBjYW4gYmUgZmVkIGludG8gbGF0ZXIgZnVuY3Rpb25zCiMnIEBleHBvcnQKIycKIycgQGV4YW1wbGVzIC0gZGF0YV9wdWxsKCJTUFkiKQpkYXRhX3B1bGwgPSBmdW5jdGlvbihzeW1ib2wsIGNvbXBsX2Nhc2UgPSAxLCBhZGpfY2xvc2UgPSAxLCBsb2dfcmV0dXJuID0gMSwgc3RhcnRfZGF0ZSA9ICIxOTAwLTAxLTAxIiwgZW5kX2RhdGUgPSBTeXMuRGF0ZSgpKXsKICAjIFB1bGwgaW4gZGF0YSBmcm9tIHF1YW50bW9kCiAgcmVzcG9uc2VfcHVsbCA9IGdldFN5bWJvbHMoc3ltYm9sLCBhdXRvLmFzc2lnbiA9IEZBTFNFLCBmcm9tID0gc3RhcnRfZGF0ZSwgdG8gPSBlbmRfZGF0ZSkKICAjIEdldCBhZGp1c3RlZCBjbG9zaW5nIHByaWNlCiAgaWYgKGFkal9jbG9zZSA9PSBUUlVFKXsKICAgIGRmID0gQWQocmVzcG9uc2VfcHVsbCkKICB9IGVsc2UgewogICAgZGYgPSBDbChyZXNwb25zZV9wdWxsKQogIH0KICAjIFJldHVybiBjb21wbGV0ZSBjYXNlcyBvbmx5IAogIGlmIChjb21wbF9jYXNlID09IFRSVUUpewogICAgZGYgPSBkZltjb21wbGV0ZS5jYXNlcyhkZiksIF0KICB9IGVsc2V7CiAgICBkZiA9IGRmCiAgfQogICMgQ2FsY3VsYXRlIGxvZyByZXR1cm4gb2YgZGF0YQogIGlmIChsb2dfcmV0dXJuID09IFRSVUUpewogICAgbHIgPSBsb2coZGZbLDFdL3NoaWZ0KGRmWywxXSwgMSwgdHlwZSA9ICJsYWciKSkKICAgICMgQ29tYmluZSBkYXRhCiAgICBkZl9vdXQgPSBjYmluZChkZiwgbHIpCiAgICAjIFJlbmFtZSB0aGUgZGF0YSAKICAgIGNvbG5hbWVzKGRmX291dCkgPC0gYyhzeW09c3ltYm9sLCBwYXN0ZTAoc3ltYm9sLCAiX2xvZ19yZXR1cm4iKSkKICB9IGVsc2V7CiAgICBkZl9vdXQgPSBkZgogIH0KICAjIFJldHVybiBkYXRhCiAgcmV0dXJuKGRmX291dCkKfQoKCmBgYAoKYGBge3J9CiMnIFB1bGwgdGhlIGRhdGEgYW5kIHJ1biB0aGUgQ0FWaWFSIGZ1bmN0aW9uIG9uIGl0CiMnCiMnIEBwYXJhbSBpbnB1dF9kYXRhIC0gZGF0YSB0byB1c2UgaW4gdGhlIGZ1bmN0aW9uCiMnIEBwYXJhbSByYW5nZV9kYXRhIC0gcmFuZ2Ugb2YgdGhlIGRhdGEgdG8gdXNlCiMnCiMnIEByZXR1cm4gLSBhIGxpc3Qgb2YgdmFsdWVzIGZyb20gdGhlIGNhdmlhciBmdW5jdGlvbgojJyBAZXhwb3J0CiMnCiMnIEBleGFtcGxlcyAtIGNhdmlhcl9wdWxsKHNweSkKY2F2aWFyX3B1bGwgPSBmdW5jdGlvbihpbnB1dF9kYXRhLCByYW5nZV9kYXRhID0gKDI6ZGltKGlucHV0X2RhdGEpWzFdKSl7CiAgIyBSdW4gdGhlIGNhdmlhciBkYXRhCiAgY2F2aWFyIDwtIGNhdmlhck9wdGltKGlucHV0X2RhdGFbcmFuZ2VfZGF0YSwyXSkKICByZXR1cm4oY2F2aWFyKQp9CgpgYGAKCgpgYGB7cn0KIycgRnVuY3Rpb24gZm9yIHByb2R1Y2luZyByb2xsaW5nIHByZWRpY3Rpb25zCiMnIE1vZGVsIDEgPSBTeW1tZXRyaWMgQWJzb2x1dGUgVmFsdWUsIDIgPSBBc3ltbWV0cmljIHNsb3BlLCAzID0gSW5kaXJlY3QgR0FSQ0gsIDQgPSBBZGFwdGl2ZQojJwojJyBAcGFyYW0gaW5wdXRfZGF0YSAtIGlucHV0IGRhdGEgZnJvbSB0aGUgcHJldmlvdXMgZnVuY3Rpb24KIycgQHBhcmFtIHJhbmdlX2RhdGEgLSByYW5nZSBvZiB0aGUgZGF0YSB0byBjb25zaWRlcgojJyBAcGFyYW0gbmZjc3QgLSBudW1iZXIgb2YgZm9yZWNhc3RzIHRvIG1ha2UKIycgQHBhcmFtIG1vZGVsIC0gbW9kZWwgdG8gdXNlIChpbnRlZ2VycyAxIHRocm91Z2ggNCkuIERlZmF1bHRzIHRvIDEuIAojJyBAcGFyYW0gbGV2ZWwgLSBsZXZlbCBvZiBzaWduaWZpY2FuY2UgdG8gdXNlLgojJyBAcGFyYW0gRyAtIGFyZ3VtZW50IGZvciB0aGUgayBwYXJhbWV0ZXIgaW4gdGhlIDR0aCBtb2RlbCAoYWRhcHRpdmUpLiBEZWZhdWx0IGlzIDUKIycKIycgQHJldHVybiAtIGFuIHh0cyBvYmplY3Qgd2hpY2ggY29udGFpbnMgcm9sbGluZyBDQVZpYVIgcHJlZGljdGlvbnMKIycgQGV4cG9ydAojJwojJyBAZXhhbXBsZXMgLSByb2xsaW5nX3ByZWRpY3Rpb25zKHNweSwgbmZjc3QgPSAyMikKcm9sbGluZ19wcmVkaWN0aW9ucyA9IGZ1bmN0aW9uKGlucHV0X2RhdGEsIHJhbmdlX2RhdGEgPSAoMjpkaW0oaW5wdXRfZGF0YSlbMV0pLCBuZmNzdCA9IDI1MCwgbW9kZWwgPTEsIGxldmVsID0gMC4wMSwgRyA9IDUsIGNvbCA9IDIpewogICMgUnVuIHRoZSB2YXJwcmVkaWN0IGZ1bmN0aW9uCiAgdmFycHJlZGljdCA8LSByb2xsYXBwbHlyKGlucHV0X2RhdGFbcmFuZ2VfZGF0YSxjb2xdLCBsZW5ndGgocmFuZ2VfZGF0YSkgLSBuZmNzdCwgY2F2aWFyT3B0aW0sIG1vZGVsLCBsZXZlbCwgcHJlZGljdCA9IDEsIGsgPSBHKSAlPiUgbGFnCiAgIyBFbGltaW5hdGUgTkFzCiAgIyBwcmVkX25vX25hID0gbmEub21pdCh2YXJwcmVkaWN0KQogICMgUmV0dXJuIHRoZSBkYXRhCiAgIyByZXR1cm4ocHJlZF9ub19uYSkKICByZXR1cm4odmFycHJlZGljdCkKfQoKYGBgCgpgYGB7cn0KIycgRnVuY3Rpb24gdG8gQ2FsY3VsYXRlIExvc3MgZnJvbSB0aGUgYWJvdmUgcHJlZGljdGlvbnMKIycKIycgQHBhcmFtIHN5bWJvbCAtIHN5bWJvbCB0byB3b3JrIHdpdGggZnJvbSBxdWFudG1vZC4gTXVzdCBiZSBpbiBxdW90YXRpb25zIHRvIHdvcmsKIycgQHBhcmFtIHN0YXJ0X2R0IC0gc3RhcnQgZGF0ZSBvZiB0aGUgZGF0YSB0byBidWlsZCB0aGUgZm9yZWNhc3Qgb24gCiMnIEBwYXJhbSBlbmRfZHQgLSBlbmQgZGF0ZSBvZiB0aGUgZGF0YSB0byBidWlsZCB0aGUgZm9yZWNhc3Qgb24gIAojJyBAcGFyYW0gbmZjc3QgLSBudW1iZXIgb2YgZGF0YSBwb2ludHMgdG8gdXNlIGluIHRoZSBmb3JlY2FzdAojJyBAcGFyYW0gbW9kZWwgLSBtb2RlbCB0byB1c2UuIERlZmF1bHRzIHRvIDEKIycgQHBhcmFtIGxldmVsIC0gbGV2ZWwgb2Ygc2lnbmlmaWNhbmNlLiBEZWZhdWx0cyB0byAxJQojJyBAcGFyYW0gRyAtIGFyZ3VtZW50IGZvciB0aGUgayBwYXJhbWV0ZXIgaW4gdGhlIDR0aCBtb2RlbCAoYWRhcHRpdmUpLiBEZWZhdWx0IGlzIDUKIycKIycgQHJldHVybiAtIGxvc3MgdXNpbmcgYWJzb2x1dGUgdmFsdWUKIycgQGV4cG9ydCAtIGEgcGxvdCBvZiB0aGUgZGF0YQojJwojJyBAZXhhbXBsZXMKbG9zc19jYWxjX3V2ID0gZnVuY3Rpb24oc3ltYm9sLCBzdGFydF9kdCwgZW5kX2R0LCBuZmNzdCwgbW9kZWwgPSAxLCBsZXZlbCA9IDAuMDEsIEcgPSA1KXsKICAjIFB1bGwgaW4gdGhlIGRhdGEKICByYXdfZGF0YSA9IGRhdGFfcHVsbChzeW1ib2wsIHN0YXJ0X2RhdGUgPSBzdGFydF9kdCwgZW5kX2RhdGUgPSBlbmRfZHQpCiAgIyBGb3JlY2FzdCBiYXNlZCBvbiB0aGUgZGF0YQogIGZjc3QgPSBuYS5vbWl0KHJvbGxpbmdfcHJlZGljdGlvbnMocmF3X2RhdGEsIG5mY3N0ID0gbmZjc3QsIG1vZGVsID0gbW9kZWwsIGxldmVsID0gbGV2ZWwsIEcgPSBHKSkqKC0xKQogICMgRXh0cmFjdCBhY3R1YWxzCiAgYWN0ID0gdGFpbChyYXdfZGF0YSwgbiA9IG5mY3N0KVssMl0KICAjIEpvaW4gdGhlIHR3byB0b2dldGhlciBhbmQgcmVuYW1lCiAgam9pbiA9IG1lcmdlKGZjc3QsYWN0LGFsbD1UUlVFKQogIGNvbG5hbWVzKGpvaW4pIDwtIGMoIkZjc3RfVmFSIiwgIkFjdF9SZXR1cm4iKQogICMgcHJpbnQoam9pbikKICAjIENhbGN1bGF0ZSB0aGUgbG9zc2VzCiAgbG9zcyA9IGFicyhzdW0oaWZlbHNlKGFjdCA+IGZjc3QsIGxldmVsLCAoLTEpKigxLWxldmVsKSkpKQogICMgUGxvdCB0aGUgZGF0YQogIHBsb3QgPSBwbG90Lnh0cyhqb2luLCBjb2wgPSBjKCJyZWQiLCAiYmxhY2siKSwgbHR5ID0gYygyLDEpLCBtYWluID0gIkxvZyBSZXR1cm4gZnJvbSB0aGUgU1BZIHZzLiBGY3N0LiBWYVIiLGdyaWQuY29sID0gTkEsIGxlZ2VuZC5sb2MgPSAiYm90dG9tbGVmdCIpCiAgcmV0dXJuKGxpc3QobG9zcywgcGxvdCwgYWN0LCBmY3N0KSkKfQoKYGBgCgoKYGBge3IsIGNhY2hlID0gVFJVRX0KIycgVGhpcyBpcyBhIGZ1bmN0aW9uIHdoaWNoIGNyZWF0ZXMgYSBkYXRhIGZyYW1lIGZvciB0aGUgcmVzcG9uc2UgYW5kIGV4cGxhbmF0b3J5IHZhcmlhYmxlcyB0aGF0IHdlJ2xsIGZlZWQgaW50byB0aGUgZGlmZnVzaW9uIGluZGV4CiMnCiMnIEBwYXJhbSBzeW1ib2xfbGlzdCAtIGEgbGlzdCBvZiBzeW1ib2xzIHJlY29nbml6YWJsZSBieSB0aGUgCiMnIEBwYXJhbSByZXNwX3ZhciAtIHRoZSByZXNwb25zZSB2YXJpYWJsZSB3ZSdkIGxpa2UgdG8gZm9yZWNhc3Q7IGRlZmF1bHQgaXMgU1BZCiMnIEBwYXJhbSBjb21wbF9jYXNlIC0gZGVmYXVsdHMgdG8gdHJ1ZS4uLm9ubHkgaW5jbHVkZXMgY29tcGxldGUgY2FzZXMgaW4gdGhlIGRhdGEKIycgQHBhcmFtIGFkal9jbG9zZSAtIHVzZSBhZGp1c3RlZCBjbG9zaW5nIHByaWNlcyBmb3IgdGhlIGV4cGxhbmF0b3J5IHZhcmlhYmxlcz8gZGVmYXVsdCBpcyAxIGZvciBZRVMKIycgQHBhcmFtIHJlc3BfYWRqX2Nsb3NlIC0gdXNlIGFkanVzdGVkIGNsb3NpbmcgcHJpY2VzIGZvciB0aGUgZXhwbGFuYXRvcnkgdmFyaWFibGVzPyBkZWZhdWx0IGlzIDEgZm9yIFlFUwojJyBAcGFyYW0gc3RhcnRfZGF0ZSAtIHN0YXJ0aW5nIGRhdGEgdG8gdXNlCiMnIEBwYXJhbSBlbmRfZGF0ZSAtIGVuZGluZyBkYXRlIG9mIHRoZSBkYXRhCiMnIEBwYXJhbSBsYWdfcHJlZCAtIGRvIHdlIGxhZyB0aGUgcHJlZGljdGlvbnM/IEl0IGlzIFNUUk9OR0xZIHJlY29tbWVuZGVkIHRoYXQgdGhpcyBpcyAwCiMnCiMnIEByZXR1cm4gLSBhIGRhdGEgZnJhbWUgd2hpY2ggY2FuIGJlIGZlZCBpbnRvIHRoZSBTV2ZvcmUgZnVuY3Rpb24KIycgQGV4cG9ydAojJwojJyBAZXhhbXBsZXMgLSBkaWZmX2luZGV4X2RmKGMoIlhMRiIsICJYTEUiLCAiUFNDVCIsICJYTFYiLCAiVlBVIiwgIlhMUCIsICJJR0YiLCAiWFdFQiIsICJQUFRZIikpCmRpZmZfaW5kZXhfZGYgPSBmdW5jdGlvbihzeW1ib2xfbGlzdCwgcmVzcF92YXIgPSAiU1BZIiwgY29tcGxfY2FzZSA9IDEsIGFkal9jbG9zZSA9IDEsIHJlc3BfYWRqX2Nsb3NlID0gMSwgc3RhcnRfZGF0ZSA9ICIxOTAwLTAxLTAxIiwgZW5kX2RhdGUgPSBTeXMuRGF0ZSgpLCBsYWdfcHJlZCA9IDEpewogICMgUHVsbCBpbiByZXNwb25zZSB2YXJpYWJsZQogIHJlc3BvbnNlX3B1bGwgPSBnZXRTeW1ib2xzKHJlc3BfdmFyLCBhdXRvLmFzc2lnbiA9IEZBTFNFLCBmcm9tID0gc3RhcnRfZGF0ZSwgdG8gPSBlbmRfZGF0ZSkKICAjIEdldCBhZGp1c3RlZCBjbG9zaW5nIHByaWNlCiAgaWYgKHJlc3BfYWRqX2Nsb3NlID09IFRSVUUpewogICAgZGlmZl9kZiA9IEFkKHJlc3BvbnNlX3B1bGwpCiAgfSBlbHNlIHsKICAgIGRpZmZfZGYgPSBDbChyZXNwb25zZV9wdWxsKQogIH0KICAjIExvb3AgdGhyb3VnaCB0aGUgc3ltYm9scyBhbmQgam9pbiBpbiBkYXRhCiAgZm9yIChpIGluIDE6bGVuZ3RoKHN5bWJvbF9saXN0KSl7CiAgICAjIFB1bGwgY2xvc2luZyBwcmljZQogICAgZXhwbF9wdWxsID0gZ2V0U3ltYm9scyhzeW1ib2xfbGlzdFtpXSwgYXV0by5hc3NpZ24gPSBGQUxTRSwgZnJvbSA9IHN0YXJ0X2RhdGUsIHRvID0gZW5kX2RhdGUpCiAgICAjIEV4dHJhY3QgY2xvc2luZyBwcmljZSAtIDR0aCBlbGVtZW50CiAgICBpZiAoYWRqX2Nsb3NlID09IFRSVUUpewogICAgICBleHBsX2NsID0gQWQoZXhwbF9wdWxsKQogICAgfSBlbHNlIHsKICAgICAgZXhwbF9jbCA9IENsKGV4cGxfcHVsbCkKICAgIH0KICAgICMgTmV3IGNvZGUgZm9yIDQuMTYuMjAyMCAtIGxhZyB0aGUgZXhwbGFuYXRvcnkgdmFyaWFibGVzCiAgICBpZiAobGFnX3ByZWQgPT0gVFJVRSl7CiAgICAgICMgTGFnIHRoZSBleHBsYW5hdG9yeSB2YXJpYWJsZXMgYnkgMQogICAgICBsYWdfZXhwID0gbGFnKGV4cGxfY2wsIDEpCiAgICAgICMgQXBwZW5kIHRoZSBmaXJzdCBsYWcgdG8gdGhlIGRhdGEgZnJhbWUKICAgICAgZGlmZl9kZiA9IG1lcmdlKGRpZmZfZGYsIGxhZ19leHAsIGpvaW4gPSAibGVmdCIsIGZpbGwgPSBOQSkKICAgIH0gZWxzZXsKICAgICAgIyBSZXR1cm4gdGhlIGRhdGEgZnJhbWUgd2l0aG91dCBsYWdzCiAgICAgIGRpZmZfZGYgPSBtZXJnZShkaWZmX2RmLCBleHBsX2NsLCBqb2luID0gImxlZnQiLCBmaWxsID0gTkEpCiAgICB9CiAgfQogIGlmIChsYWdfcHJlZCA9PSBUUlVFKXsKICAgICMgQ2hvcCBvZmYgdGhlIGZpcnN0IHJvdwogICAgZGlmZl9kZiA9IGRpZmZfZGZbLTEsXQogIH0KICBlbHNlIHsKICAgIHByaW50KCJQTEVBU0UgTk9URSAtIHRoZSBleHBsYW5hdG9yeSB2YXJpYWJsZXMgaW4gdGhpcyBERiBhcmUgTk9UIGxhZ2dlZC4gQmUgY2FyZWZ1bCB0byBhdm9pZCBsb29rLWFoZWFkIGJpYXMhIikKICB9CiAgIyBSZXR1cm4gY29tcGxldGUgY2FzZXMgb25seSAKICBpZiAoY29tcGxfY2FzZSA9PSBUUlVFKXsKICAgIGRpZmZfZGZfb3V0ID0gZGlmZl9kZltjb21wbGV0ZS5jYXNlcyhkaWZmX2RmKSwgXQogIH0gZWxzZXsKICAgIGRpZmZfZGZfb3V0ID0gZGlmZl9kZgogIH0KICAKICByZXR1cm4oZGlmZl9kZl9vdXQpCn0KCmBgYAoKYGBge3IsIGNhY2hlID0gVFJVRX0KIycgQ29udmVydHMgYSBkaWZmX2RmIGludG8gYSBkYXRhIGZyYW1lIHdpdGggYXBwcm94aW1hdGUgcGVyY2VudGFnZSBjaGFuZ2VzIGRpZmYobG9nKGRpZmZfZGYpKQojJwojJyBAcGFyYW0gZGlmZl9kZiAtIG91dHB1dCBvZiB0aGUgZGlmZl9pbmRleF9kZiBmdW5jdGlvbiB3aXRoIGNvbXBsZXRlIGNhc2VzCiMnCiMnIEByZXR1cm4gLSByZXR1bnMgdGhlIGRpZmZlcmVuY2VkIGRhdGEKIycgQGV4cG9ydAojJwojJyBAZXhhbXBsZXMgLSBwY19kaWZmX2luZGV4KHRlc3RfY29tcGwpIAoKcGNfZGlmZl9pbmRleCA9IGZ1bmN0aW9uKGRpZmZfZGYpewogICMgRGlmZmVyZW5jZSB0aGUgbG9nIG9mIHRoZSBkYXRhCiAgcGNfZGlmZl9pbmRleCA9IGRpZmYobG9nKGRpZmZfZGYpKQogICMgUmVtb3ZlIHRoZSBmaXJzdCByb3cKICBwY19kaWZmX2luZGV4X291dCA9IHBjX2RpZmZfaW5kZXhbLTEsXQogIHJldHVybihwY19kaWZmX2luZGV4X291dCkKfQoKYGBgCgoKYGBge3J9CiMnIEJlbG93IGlzIHRoZSBtb2RpZmllZCBkaWZmdXNpb24gaW5kZXggY29kZS4KIycKIycgQHBhcmFtIHkgLSByZXNwb25zZSB2YXJpYWJsZQojJyBAcGFyYW0geCAtIHByZWRpY3RvciB2YXJpYWJsZXMKIycgQHBhcmFtIG9yaWcgLSBmb3JlY2FzdCBvcmlnaW4KIycgQHBhcmFtIG0gLSBudW1iZXIgb2YgZGlmZnVzaW9uIGluZGV4ZXMgdXNlZAojJyBAcGFyYW0gdGF1IC0gVmFSIGxldmVsIHRvIHVzZTsgbXVzdCBiZSBiZXR3ZWVuIDAgYW5kIDEKIycgQHBhcmFtIGVuZCAtIHNwZWNpZmllcyBhbiBhbHRlcm5hdGUgZW5kaW5nIHZhbHVlCiMnIEBwYXJhbSBwcmludF9tZGwgLSBwcmludCB0aGUgbW9kZWwgc3VtbWFyeSBhbmQgdGhlIE1TRQojJwojJyBAcmV0dXJuIC0gcmV0dXJucyBhIGxpc3Qgb2YgdmFyaWFibGVzIGZvciB1c2UgaW4gdGhlIGRpZmZ1c2lvbiBpbmRleAojJyBAZXhwb3J0CiMnCiMnIEBleGFtcGxlcwptb2RfZGkgPSBmdW5jdGlvbiAoeSwgeCwgb3JpZywgbSwgdGF1LCBlbmQgPSBOVUxMLCBwcmludF9tZGwgPSAwKSAKewogICMgQ29udmVydHMgdGhlIHJlc3BvbnNlIHZhcmlhYmxlcyBpbnRvIGEgbWF0cml4CiAgaWYgKCFpcy5tYXRyaXgoeCkpIAogICAgICB4ID0gYXMubWF0cml4KHgpCiAgIyBuVCBpcyBudW1iZXIgb2YgdCB0aW1lLXN0ZXBzCiAgblQgPSBkaW0oeClbMV0KICAjIEFkZCBhIGxpbmUgdG8gZXN0YWJsaXNoIHRoZSBudW1iZXIgb2YgZGF0YSBwb2ludHMgdXNlZCBpbiB0aGUgdGVzdC4KICBpZiAoaXMubnVsbChlbmQpICE9IFRSVUUpewogICAgblQgPSBlbmQKICB9CiAgIyBrIGlzIHRoZSBudW1iZXIgb2YgZGlmZnVzaW9uIGluZGljZXMgdXNlZAogIGsgPSBkaW0oeClbMl0KICAjIFNhbml0eSBjaGVja3MgdG8gZW5zdXJlIHRoYXQgdGhlIG9yaWdpbiBpc24ndCBwYXN0IHRoZSBudW1iZXIgb2YgdGltZSBwb2ludHMKICBpZiAob3JpZyA+IG5UKSAKICAgICAgb3JpZyA9IG5UCiAgIyBNYWtlcyBzdXJlIHRoYXQgdGhlcmUgYXJlbid0IG1vcmUgcHJlZGljdG9ycyB0aGFuIHRoZXJlIHZhcmlhYmxlcyBpbiB0aGUgZGF0YXNldAogIGlmIChtID4gaykgCiAgICAgIG0gPSBrCiAgIyBNYWtlcyBzdXJlIHRoZXJlIGFyZSBhdCBsZWFzdCBzb21lIHZhcmlhYmxlcwogIGlmIChtIDwgMSkgCiAgICAgIG0gPSAxCiAgIyBTdWJkaXZpZGVzIHRoZSBkYXRhZnJhbWUKICB4MSA9IHhbMTpvcmlnLCBdCiAgIyBDYWxjdWxhdGVzIG1lYW5zIG9mIGVhY2ggcm93CiAgbWUgPSBhcHBseSh4MSwgMiwgbWVhbikKICAjIENhbGN1bGF0ZXMgc3RhbmRhcmQgZGV2aWF0aW9ucyBvZiBlYWNoIGNvbHVtbgogIHNlID0gc3FydChhcHBseSh4MSwgMiwgdmFyKSkKICAjIENyZWF0ZXMgYSBtYXRyaXggeDEsIHdoaWNoIG5vcm1hbGl6ZXMgYWxsIHRoZSBjb2x1bW5zLiAKICAjIFRoaXMgbWF5IGJlIGFuIGlzc3VlIHNpbmNlIGl0IGFzc3VtZXMgdGhhdCB0aGUgZGlzdHJpYnV0aW9uIGlzIHN1ZmZpY2llbnRseSBkZXNjcmliZWQgYnkgdGhlIGZpcnN0IHR3byBtb21lbnRzCiAgeDEgPSB4CiAgZm9yIChpIGluIDE6aykgewogICAgICB4MVssIGldID0gKHgxWywgaV0gLSBtZVtpXSkvc2VbaV0KICB9CiAgVjEgPSBjb3YoeDFbMTpvcmlnLCBdKQogICMgUGVyZm9ybXMgYW4gZWlnZW4gZGVjb21wb3NpdGlvbgogIG0xID0gZWlnZW4oVjEpCiAgIyBTZWxlY3RzIGVpZ2VudmFsdWVzCiAgc2RldiA9IG0xJHZhbHVlcwogICMgU2VsZWN0cyBlaWdlbnZlY3RvcnMKICBNID0gbTEkdmVjdG9ycwogICMgTWFrZXMgYSBzbWFsbGVyIG1hdHJpeAogIE0xID0gTVssIDE6bV0KICAjIFRoaXMgaXMgdGhlIGRpZmZ1c2lvbiBpbmRleCBtb2RlbCAtIFtvcmlnIHggcF0qW3AgeCBtXSA9IFtvcmlnIHggbV0KICBEaW5kZXggPSB4MSAlKiUgTTEKICAjIEN1dCBkb3duIGJvdGggdGhlIHJlc3BvbnNlIGFuZCBwcmVkaWN0b3JzIHRvIGJlIGEgcmVhc29uYWJsZSBzaXplCiAgeTEgPSB5WzE6b3JpZ10KICBERiA9IERpbmRleFsxOm9yaWcsIF0KICAjIEFwcGx5IHRoZSBsaW5lYXIgbW9kZWwgLSBIRVJFIGlzIHRoZSBrZXkuCiAgIyBtbSA9IGxtKHkxIH4gREYpIC0gb2xkIGZ1bmN0aW9uCiAgbW0gPSBycSh5MSB+IERGLCB0YXUgPSB0YXUpCiAgIyBQcmludCB0aGUgZGF0YQogIGlmIChwcmludF9tZGwgPT0gMSl7CiAgICBwcmludChzdW1tYXJ5KG1tKSkKICB9CiAgIyBQdXRzIGNvZWZmaWNpZW50cyBpbiBhIG1hdHJpeAogIGNvZWYgPSBtYXRyaXgobW0kY29lZmZpY2llbnRzLCAobSArIDEpLCAxKQogICMgSW5pdGlhbGl6ZXMgeWhhdCB2YXJpYWJsZXMgYW5kIE1TRQogIHloYXQgPSBOVUxMCiAgTVNFID0gTlVMTAogIGlmIChvcmlnIDwgblQpIHsKICAgICMgQ3JlYXRlcyBhIG5mY3N0IGJ5IChtKzEpIG1hdHJpeAogICAgbmV3eCA9IGNiaW5kKHJlcCgxLCAoblQgLSBvcmlnKSksIERpbmRleFsob3JpZyArIDEpOm5ULCAKICAgICAgICBdKQogICAgIyBbbmZjc3R4KG0rMSldKlsobSsxKXgxXSA9IFtuZmNzdHgxXQogICAgeWhhdCA9IG5ld3ggJSolIGNvZWYKICAgICMgQ2FsY3VsYXRlcyBlcnJvcnMKICAgIGVyciA9IHlbKG9yaWcgKyAxKTpuVF0gLSB5aGF0CiAgICBNU0UgPSBtZWFuKGVycl4yKQogICAgaWYgKHByaW50X21kbCA9PSAxKXsKICAgICAgY2F0KCJNU0Ugb2Ygb3V0LW9mLXNhbXBsZSBmb3JlY2FzdHM6ICIsIE1TRSwgIlxuIikKICAgIH0KICB9CiAgU1dmb3JlIDwtIGxpc3QoY29lZiA9IGNvZWYsIHloYXQgPSB5aGF0LCBNU0UgPSBNU0UsIGxvYWRpbmdzID0gTTEsIAogICAgICBERmluZGV4ID0gRGluZGV4KQp9CgpgYGAKCgpgYGB7cn0KIycgQmVsb3cgaXMgdGhlIG1vZGlmaWVkIGRpZmZ1c2lvbiBpbmRleCBjb2RlIHRvIGluY2x1ZGUgbGFnZ2VkIHZhcmlhYmxlcy4KIycKIycgQHBhcmFtIHkgLSByZXNwb25zZSB2YXJpYWJsZQojJyBAcGFyYW0geCAtIHByZWRpY3RvciB2YXJpYWJsZXMKIycgQHBhcmFtIG9yaWcgLSBmb3JlY2FzdCBvcmlnaW4KIycgQHBhcmFtIG0gLSBudW1iZXIgb2YgZGlmZnVzaW9uIGluZGV4ZXMgdXNlZAojJyBAcGFyYW0gdGF1IC0gVmFSIGxldmVsIHRvIHVzZTsgbXVzdCBiZSBiZXR3ZWVuIDAgYW5kIDEKIycgQHBhcmFtIGFyX3RmIC0gQVIgdHJhbnNmb3JtYXRpb24gdHlwZS4gKDEgLSBubyB0cmFuc2Zvcm1hdGlvbiwKIycgMiAtIGFic29sdXRlIHZhbHVlLCAzIC0gYXN5bW1ldHJpYyBzbG9wZSkKIycgQHBhcmFtIHAgLSBudW1iZXIgb2YgQVIgbGFncyB0byBpbmNsdWRlLiBEZWZhdWx0IGlzIG9uZS4KIycgQHBhcmFtIHByaW50X21kbCAtIG9wdGlvbiB0byBwcmludCB0aGUgbW9kZWwgc3VtbWFyeSB0byBtYWtlIHN1cmUgZXZlcnl0bmluZyBpcyBvay4gMCBpcyBkZWZhdWx0LgojJyBAcGFyYW0gbW9kZWwgLSBtb2RlbCB0eXBlICgxIC0gU0FWLCAyIC0gQVMsIDMgLSBHQVJDSCwgNCAtIEFEQVBUSVZFKSAKIycKIycgQHJldHVybiAtIHJldHVybnMgYSBsaXN0IG9mIHZhcmlhYmxlcyBmb3IgdXNlIGluIHRoZSBkaWZmdXNpb24gaW5kZXgKIycgQGV4cG9ydAojJwojJyBAZXhhbXBsZXMKbW9kX2RpX3dsID0gZnVuY3Rpb24gKHksIHgsIG9yaWcsIG0sIHRhdSwgYXJfdGYgPSAxLCBwID0gMSwgcHJpbnRfbWRsID0gMCwgbW9kZWwgPSAxLCBlbmQgPSBOVUxMKSAKewogICMgQ29udmVydHMgdGhlIHJlc3BvbnNlIHZhcmlhYmxlcyBpbnRvIGEgbWF0cml4CiAgaWYgKCFpcy5tYXRyaXgoeCkpIAogICAgICB4ID0gYXMubWF0cml4KHgpCiAgIyBuVCBpcyBudW1iZXIgb2YgdCB0aW1lLXN0ZXBzCiAgblQgPSBkaW0oeClbMV0KICAjIEFkZCBhIGxpbmUgdG8gZXN0YWJsaXNoIHRoZSBudW1iZXIgb2YgZGF0YSBwb2ludHMgdXNlZCBpbiB0aGUgdGVzdC4KICBpZiAoaXMubnVsbChlbmQpICE9IFRSVUUpewogICAgblQgPSBlbmQKICB9CiAgIyBrIGlzIHRoZSBudW1iZXIgb2YgZGlmZnVzaW9uIGluZGljZXMgdXNlZAogIGsgPSBkaW0oeClbMl0KICAjIFNhbml0eSBjaGVja3MgdG8gZW5zdXJlIHRoYXQgdGhlIG9yaWdpbiBpc24ndCBwYXN0IHRoZSBudW1iZXIgb2YgdGltZSBwb2ludHMKICBpZiAob3JpZyA+IG5UKSAKICAgICAgb3JpZyA9IG5UCiAgIyBNYWtlcyBzdXJlIHRoYXQgdGhlcmUgYXJlbid0IG1vcmUgcHJlZGljdG9ycyB0aGFuIHRoZXJlIHZhcmlhYmxlcyBpbiB0aGUgZGF0YXNldAogIGlmIChtID4gaykgCiAgICAgIG0gPSBrCiAgIyBNYWtlcyBzdXJlIHRoZXJlIGFyZSBhdCBsZWFzdCBzb21lIHZhcmlhYmxlcwogIGlmIChtIDwgMSkgCiAgICAgIG0gPSAxCiAgIyBTdWJkaXZpZGVzIHRoZSBkYXRhZnJhbWUKICB4MSA9IHhbMTpvcmlnLCBdCiAgIyBDYWxjdWxhdGVzIG1lYW5zIG9mIGVhY2ggcm93CiAgbWUgPSBhcHBseSh4MSwgMiwgbWVhbikKICAjIENhbGN1bGF0ZXMgc3RhbmRhcmQgZGV2aWF0aW9ucyBvZiBlYWNoIGNvbHVtbgogIHNlID0gc3FydChhcHBseSh4MSwgMiwgdmFyKSkKICAjIENyZWF0ZXMgYSBtYXRyaXggeDEsIHdoaWNoIG5vcm1hbGl6ZXMgYWxsIHRoZSBjb2x1bW5zLiAKICAjIFRoaXMgbWF5IGJlIGFuIGlzc3VlIHNpbmNlIGl0IGFzc3VtZXMgdGhhdCB0aGUgZGlzdHJpYnV0aW9uIGlzIHN1ZmZpY2llbnRseSBkZXNjcmliZWQgYnkgdGhlIGZpcnN0IHR3byBtb21lbnRzCiAgeDEgPSB4CiAgZm9yIChpIGluIDE6aykgewogICAgICB4MVssIGldID0gKHgxWywgaV0gLSBtZVtpXSkvc2VbaV0KICB9CiAgVjEgPSBjb3YoeDFbMTpvcmlnLCBdKQogICMgUGVyZm9ybXMgYW4gZWlnZW4gZGVjb21wb3NpdGlvbgogIG0xID0gZWlnZW4oVjEpCiAgIyBTZWxlY3RzIGVpZ2VudmFsdWVzCiAgc2RldiA9IG0xJHZhbHVlcwogICMgU2VsZWN0cyBlaWdlbnZlY3RvcnMKICBNID0gbTEkdmVjdG9ycwogICMgTWFrZXMgYSBzbWFsbGVyIG1hdHJpeAogIE0xID0gTVssIDE6bV0KICAjIFRoaXMgaXMgdGhlIGRpZmZ1c2lvbiBpbmRleCBtb2RlbCAtIFtvcmlnIHggcF0qW3AgeCBtXSA9IFtvcmlnIHggbV0KICBEaW5kZXggPSB4MSAlKiUgTTEKICAjIEN1dCBkb3duIGJvdGggdGhlIHJlc3BvbnNlIGFuZCBwcmVkaWN0b3JzIHRvIGJlIGEgcmVhc29uYWJsZSBzaXplCiAgeTEgPSB5WzE6b3JpZ10KICBERiA9IERpbmRleFsxOm9yaWcsIF0KICAjIENvcHkgdGhlIGRhdGEgZnJhbWUKICBERl93bCA9IERpbmRleAogICMgTGFnIHRoZSB5LXZhcmlhYmxlCiAgZm9yIChpIGluIDE6cCl7CiAgICAjIENyZWF0ZSBhIGxhZ2dlZCB2YXJpYWJsZQogICAgbGFnX3ZhciA9IGxhZyh5LCBpKQogICAgIyBBcHBlbmQgdGhlIGZpcnN0IGxhZyB0byB0aGUgZGF0YSBmcmFtZQogICAgREZfd2wgPSBjYmluZChERl93bCxsYWdfdmFyKQogIH0KICAjIElkZW50aWZ5IHRoZSByaWdodCBjb2x1bW5zCiAgbF9hciA9IG5jb2woREZfd2wpCiAgZl9hciA9IGxfYXIgLSBwICsgMQogICMgS2VlcCB0aGUgbGFzdCBjb2x1bW5zIGtlcHQgdG8gdGhlIHNpZGUKICBhbGxfbGFnID0gREZfd2xbLChmX2FyOmxfYXIpXQogICMgQ3V0IG9mZiB0aGUgZmlyc3Qgcm93IHRvIGF2b2lkIE5BJ3MKICBERl90cmltID0gREZfd2xbMTpvcmlnLF0KICAjIFJlbmFtZSB0aGUgY29sdW1ucwogICMgSGVyZSdzIHRoZSBuZXcgZnVuY3Rpb24gd2l0aCBhbiB1bnRyYW5zZm9ybWVkIEFSKHApIGxhZwogIGlmIChhcl90ZiA9PSAxKXsKICAgICMgSW5jb3Jwb3JhdGUgZXZlcnl0aGluZyBpbiB0byBhbiBpbnB1dCBkYXRhIGZyYW1lCiAgICBkZl9pbiA9IGNiaW5kKHkxWy0oMTpwKV0sIERGX3RyaW1bLSgxOnApLF0pCiAgICAjIFJlbmFtZSB0aGUgY29sdW1ucwogICAgIyBJbml0aWFsaXplIGEgY2hhcmFjdGVyIHZlY3RvcgogICAgbnZlYyA9IGMocmVwKDAsIDErbStwKSkKICAgICMgUG9wdWxhdGUgdGhlIHZlY3RvciAtIGZpcnN0IHZhbHVlIGlzIHRoZSByZXNwb25zZQogICAgbnZlY1sxXSA8LSBuYW1lcyh5KQogICAgIyBOZXh0IGFyZSB0aGUgZGlmZnVzaW9uIGluZGljZXMKICAgIGZvciAoaSBpbiAxOm0pewogICAgICBudmVjW2krMV0gPSBwYXN0ZTAoIkRpZmZfSW5kZXhfIiwgaSkKICAgIH0KICAgICMgTmV4dCBhcmUgdGhlIGxhZ2dlZCB2YXJpYWJsZXMKICAgIGZvciAoaSBpbiAxOnApewogICAgICBudmVjW2krMSttXSA9IHBhc3RlMCgiTGFnXyIsIGkpCiAgICB9CiAgICAjIEFzc2lnbiB0aGUgbmFtZXMKICAgIG5hbWVzKGRmX2luKSA8LSBudmVjCiAgICAjIFJ1biB0aGUgbW9kZWwKICAgIG1tID0gcnEoZGZfaW5bLDFdIH4gZGZfaW5bLC0xXSwgdGF1ID0gdGF1KQogIH0KICAjIEhlcmUncyB0aGUgbmV3IGZ1bmN0aW9uIHdpdGggYW4gU0FWIEFSKHApIGxhZwogIGlmIChhcl90ZiA9PSAyKXsKICAgICMgSW5jb3Jwb3JhdGUgZXZlcnl0aGluZyBpbiB0byBhbiBpbnB1dCBkYXRhIGZyYW1lCiAgICBkZl9pbiA9IGNiaW5kKHkxWy0oMTpwKV0sIERGX3RyaW1bLSgxOnApLC0oZl9hcjpsX2FyKV0sIGFicyhERl90cmltWy0oMTpwKSwoZl9hcjpsX2FyKV0pKQogICAgIyBSZW5hbWUgdGhlIGNvbHVtbnMKICAgICMgSW5pdGlhbGl6ZSBhIGNoYXJhY3RlciB2ZWN0b3IKICAgIG52ZWMgPSBjKHJlcCgwLCAxK20rcCkpCiAgICAjIFBvcHVsYXRlIHRoZSB2ZWN0b3IgLSBmaXJzdCB2YWx1ZSBpcyB0aGUgcmVzcG9uc2UKICAgIG52ZWNbMV0gPC0gbmFtZXMoeSkKICAgICMgTmV4dCBhcmUgdGhlIGRpZmZ1c2lvbiBpbmRpY2VzCiAgICBmb3IgKGkgaW4gMTptKXsKICAgICAgbnZlY1tpKzFdID0gcGFzdGUwKCJEaWZmX0luZGV4XyIsIGkpCiAgICB9CiAgICAjIE5leHQgYXJlIHRoZSBsYWdnZWQgdmFyaWFibGVzCiAgICBmb3IgKGkgaW4gMTpwKXsKICAgICAgbnZlY1tpKzErbV0gPSBwYXN0ZTAoIkxhZ18iLCBpKQogICAgfQogICAgIyBBc3NpZ24gdGhlIG5hbWVzLiBOb3RlIHRoYXQgdGhpcyBpcyBhIG1hdHJpeAogICAgbmFtZXMoZGZfaW4pIDwtIG52ZWMKICAgICMgUnVuIHRoZSBtb2RlbAogICAgbW0gPSBycShkZl9pblssMV0gfiBkZl9pblssLTFdLCB0YXUgPSB0YXUpCiAgfQogICMgSGVyZSdzIHRoZSBuZXcgZnVuY3Rpb24gd2l0aCBhbiBhc3ltbWV0cmljIHNsb3BlIGZvciB0aGUgQVIoMSkgbGFnCiAgIyBJbmRpY2F0b3I7IDAgaWYgcGVyY2VudCBjaGFuZ2UgaXMgbmVnYXRpdmUsIDEgaWYgaXQncyBwb3NpdGl2ZQogICMgaW5kaSA9IGlmZWxzZShERl90cmltWyxhcl0gPCAwLCAwLCAxKQogIGlmIChhcl90ZiA9PSAzKXsKICAgICMgQ3JlYXRlIGEgbWF0cml4IG9mIGluZGljYXRvcnMKICAgIGluZGlfbWF0ID0gbWF0cml4KDAsIG5yb3coREZfd2wpLCBwKQogICAgIyBHZW5lcmFsaXplIHRoZSBhYm92ZSBjb2RlCiAgICBmb3IgKGkgaW4gMTpwKXsKICAgICAgIyBQb3B1bGF0ZSB0aGUgaW5kaWNhdG9yCiAgICAgIGluZGlfbWF0WyxpXSA9IGlmZWxzZShERl93bFssZl9hciArIGkgLSAxXSA8IDAsIDAsIDEpCiAgICB9CiAgfQogICMgRml0dGluZyB0aGUgcmVncmVzc2lvbgogIGlmIChhcl90ZiA9PSAzKXsKICAgICMgSW5jb3Jwb3JhdGUgZXZlcnl0aGluZyBpbiB0byBhbiBpbnB1dCBkYXRhIGZyYW1lCiAgICBkZl9pbiA9IGNiaW5kKHkxWy0oMTpwKV0sIERGX3RyaW1bLSgxOnApLC0oZl9hcjpsX2FyKV0sIERGX3RyaW1bLSgxOnApLChmX2FyOmxfYXIpXSwgaW5kaV9tYXRbKChwKzEpOm9yaWcpLF0pCiAgICAjIFJlbmFtZSB0aGUgY29sdW1ucwogICAgIyBJbml0aWFsaXplIGEgY2hhcmFjdGVyIHZlY3RvcgogICAgbnZlYyA9IGMocmVwKDAsIDErbSsyKnApKQogICAgIyBQb3B1bGF0ZSB0aGUgdmVjdG9yIC0gZmlyc3QgdmFsdWUgaXMgdGhlIHJlc3BvbnNlCiAgICBudmVjWzFdIDwtIG5hbWVzKHkpCiAgICAjIE5leHQgYXJlIHRoZSBkaWZmdXNpb24gaW5kaWNlcwogICAgZm9yIChpIGluIDE6bSl7CiAgICAgIG52ZWNbaSsxXSA9IHBhc3RlMCgiRGlmZl9JbmRleF8iLCBpKQogICAgfQogICAgIyBOZXh0IGFyZSB0aGUgbGFnZ2VkIHZhcmlhYmxlcwogICAgZm9yIChpIGluIDE6cCl7CiAgICAgIG52ZWNbaSsxK21dID0gcGFzdGUwKCJMYWdfIiwgaSkKICAgIH0KICAgICMgTGFzdCBhcmUgdGhlIHBvc2l0aXZlIGluZGljYXRvciB2YXJpYWJsZXMKICAgIGZvciAoaSBpbiAxOnApewogICAgICBudmVjW2krMSttK3BdID0gcGFzdGUwKCJQb3NfVmFsX2Zvcl9MYWdfIiwgaSkKICAgIH0KICAgICMgQXNzaWduIHRoZSBuYW1lcy4gTm90ZSB0aGF0IHRoaXMgaXMgYSBtYXRyaXgKICAgIG5hbWVzKGRmX2luKSA8LSBudmVjCiAgICAjIFJ1biB0aGUgbW9kZWwKICAgIG1tID0gcnEoZGZfaW5bLDFdIH4gZGZfaW5bLC0xXSwgdGF1ID0gdGF1KQogICAgIyBtbSA9IHJxKHkxWy0oMTpwKV0gfiBERl90cmltWy0oMTpwKSwtKGZfYXI6bF9hcildICsgREZfdHJpbVstKDE6cCksKGZfYXI6bF9hcildICsgaW5kaV9tYXRbKChwKzEpOm9yaWcpLF0sIHRhdSA9IHRhdSkKICAgICMgQWRkIGEgZGlmZmVyZW50IGxpbmUgdG8gYWNjb3VudCBmb3IgdGhlIGluZGljYXRvciB2YXJpYWJsZQogICAgIyBpbnRlcmNlcHQgKyBtICsgMipubGFnIHRvIGFjY291bnQgZm9yIHRoZSBudW1iZXIgb2YgaW5kaWNhdG9yIHZhcmlhYmxlcwogICAgY29lZiA9IG1hdHJpeChtbSRjb2VmZmljaWVudHMsICgxICsgbSArIDIqcCksIDEpCiAgfQogIGlmIChwcmludF9tZGwgPT0gMSl7CiAgICBwcmludChzdW1tYXJ5KG1tKSkKICB9CiAgIyBQdXRzIGNvZWZmaWNpZW50cyBpbiBhIG1hdHJpeCAtIGFkZGVkIHRoZSBBUiB0ZXJtcwogICMgY29lZiA9IG1hdHJpeChtbSRjb2VmZmljaWVudHMsIChtICsgMSksIDEpCiAgaWYgKGFyX3RmICE9IDMpewogICAgY29lZiA9IG1hdHJpeChtbSRjb2VmZmljaWVudHMsICgxICsgbSArIHApLCAxKQogIH0KICAjIEluaXRpYWxpemVzIHloYXQgdmFyaWFibGVzIGFuZCBNU0UKICB5aGF0ID0gTlVMTAogIGxvc3MgPSBOVUxMCiAgaWYgKG9yaWcgPCBuVCkgewogICAgIyBDcmVhdGVzIGEgbmZjc3QgYnkgKG0rMikgbWF0cml4CiAgICAjIEFkZCBvbiB0aGUgbGFnZ2VkIHZhcmlhYmxlcwogICAgbmV3eCA9IGNiaW5kKHJlcCgxLCAoblQgLSBvcmlnKSksIERpbmRleFsob3JpZyArIDEpOm5ULCBdLCBhbGxfbGFnWyhvcmlnKzEpOm5ULF0pCiAgICAjIEluY29ycG9yYXRlIGxhZ2dlZCB2YXJpYWJsZXMKICAgIGlmIChhcl90ZiA9PSAzKXsKICAgICAgbmV3eCA9IGNiaW5kKHJlcCgxLCAoblQgLSBvcmlnKSksIERpbmRleFsob3JpZyArIDEpOm5ULCBdLCBhbGxfbGFnWyhvcmlnKzEpOm5ULF0sIGluZGlfbWF0WyhvcmlnKzEpOm5ULF0pCiAgICB9CiAgICAjIFtuZmNzdHgobSsxKV0qWyhtKzEpeDFdID0gW25mY3N0eDFdCiAgICB5aGF0ID0gbmV3eCAlKiUgY29lZgogICAgIyBDYWxjdWxhdGVzIGVycm9ycwogICAgbG9zcyA9IGFicyhzdW0oaWZlbHNlKHlbKG9yaWcgKyAxKTpuVF0gPiB5aGF0LCB0YXUsICgtMSkqKDEtdGF1KSkpKQogICAgIyBNb2RpZnlpbmcgdGhpcyBwYXJ0IHRvIG9ubHkgcHJpbnQgdGhpcyBpZiBzcGVjaWZpZWQKICAgIGlmIChwcmludF9tZGwgPT0gMSl7CiAgICAgIGNhdCgiTG9zc2VzIG9mIG91dC1vZi1zYW1wbGUgZm9yZWNhc3RzOiAiLCBsb3NzLCAiXG4iKQogICAgfQogIH0KICBTV2ZvcmUgPC0gbGlzdChjb2VmID0gY29lZiwgeWhhdCA9IHloYXQsIGxvc3MgPSBsb3NzLCBsb2FkaW5ncyA9IE0xLCAKICAgICAgREZpbmRleCA9IERpbmRleCwgbmFtZV92ZWN0b3IgPSBudmVjKQp9CgpgYGAKCmBgYHtyfQojIERlY2lkZSBvbiB0aGUgb3B0aW1hbCBudW1iZXIgb2YgdmVjdG9ycy4KCiMgKHksIHgsIG9yaWcsIG0sIHRhdSkgCgojJyBGdW5jdGlvbiB0aGF0IGNhbGN1bGF0ZXMgbG9zcyBvdmVyIGEgZ2l2ZW4gcGVyaW9kIG9mIHRpbWUgZm9yIHRoZSBkaWZmdXNpb24gaW5kZXggbW9kZWwKIycKIycgQHBhcmFtIHkgLSByZXNwb25zZSB2YXJpYWJsZXMKIycgQHBhcmFtIHggLSBleHBsYW5hdG9yeSB2YXJpYWJsZQojJyBAcGFyYW0gb3JpZyAtIGZvcmVjYXN0IG9yaWdpbgojJyBAcGFyYW0gZW5kIC0gZm9yZWNhc3RpbmcgZW5kaW5nLiBOb3RlOiBhcyB0aGUgZnVuY3Rpb24gaXMgY3VycmVudGx5IHdyaXR0ZW4gb24gMi8yNCwgdGhpcyBvcHRpb24gZG9lc24ndCBkbyBhbnl0aGluZy4KIycgQHBhcmFtIG0gLSBudW1iZXIgb2YgZGlmZnVzaW9uIGluZGljZXMgdG8gdXNlCiMnIEBwYXJhbSB0YXUgLSBWYVIgbGV2ZWwKIycgQHBhcmFtIG1vZF9kaSAtIHVzZSB0aGUgbW9kaWZpZWQgREk/CiMnCiMnIEByZXR1cm4gLSByZXR1cm5zIGEgbGlzdCBvZiB0aGUgbG9zcyBzdW0gYW5kIHRoZSBsb3NzIHZlY3RvcgojJyBAZXhwb3J0CiMnCiMnIEBleGFtcGxlcyAtIGxvc3NfY2FsYyhwY19kZlssMV0sIHBjX2RmWywtMV0sIDc1NywgMTAyNywgMSwgMC4wMSkKbG9zc19jYWxjID0gZnVuY3Rpb24oeSwgeCwgb3JpZywgbSwgdGF1LCBtb2RfZGkgPSAwLCBhcl90ZiA9IDEsIHAgPSAxLCBwcmludF9tZGwgPSAwLCBtb2RlbCA9IDEsIGVuZCA9IE5VTEwpewogICMgRXh0cmFjdCB5X2hhdCB2YWx1ZXMKICBpZiAobW9kX2RpID09IDApewogICAgZGkgPSBtb2RfZGkoeT15LHg9eCxvcmlnPW9yaWcsbT1tLCB0YXU9dGF1LCBlbmQgPSBlbmQsIHByaW50X21kbCA9IHByaW50X21kbCkKICB9CiAgZWxzZSB7CiAgICBkaSA9IG1vZF9kaV93bCh5PXkseD14LG9yaWc9b3JpZyxtPW0sIHRhdT10YXUsIGFyX3RmID0gYXJfdGYsIHAgPSBwLCBwcmludF9tZGwgPSBwcmludF9tZGwsIG1vZGVsID0gbW9kZWwsIGVuZCA9IGVuZCkKICB9CiAgIyBtb2RfZGlfd2wgPSBmdW5jdGlvbiAoeSwgeCwgb3JpZywgbSwgdGF1LCBhcl90ZiA9IDEsIHAgPSAxLCBwcmludF9tZGwgPSAwLCBtb2RlbCA9IDEpCiAgeWhhdCA9IGRpJHloYXRbMTooZW5kLW9yaWcpXQogICMgQ2FsY3VsYXRlIHRoZSBsb3NzCiAgIyBJbml0aWFsaXplIGxvc3MgdmVjdG9yCiAgbHZlYyA9IHJlcCgwLChlbmQtb3JpZykpCiAgIyBUYWtlIHRoZSBkaWZmZXJlbmNlCiAgZm9yIChpIGluIDE6KGVuZC1vcmlnKSl7CiAgICAjIENhbGN1bGF0ZSBhbiBpbmRpY2F0b3IgdmFyaWFibGUKICAgIGluZCA9IGlmZWxzZSh5W29yaWcraV0gPCB5aGF0W2ldLCAxLDApCiAgICAjIFVzZSBpbmRpY2F0b3IgaW4gZnVuY3Rpb24gYmVsb3cKICAgIGx2ZWNbaV0gPSAodGF1IC0gaW5kKSooeVtvcmlnK2ldIC0geWhhdFtpXSkKICB9CiAgIyBBZGQgdXAgdGhlIGxvc3NlcyAtIGNoYW5nZSB0byBsb29rIGF0IHN1bSBvZiBsb3NzZXMuIFdvbid0IGNoYW5nZSBkZWNpc2lvbiBjcml0ZXJpb24KICBzdW1sb3NzID0gc3VtKGx2ZWMpCiAgIyBzdW1sb3NzID0gc3VtKGx2ZWMpL2xlbmd0aChsdmVjKQogIHJldHVybihsaXN0KHN1bWxvc3MsbHZlYykpCn0KCgpgYGAKCgpgYGB7cn0KIycgRnVuY3Rpb24gdGhhdCBzZWxlY3RzIHRoZSBvcHRpbWFsIG51bWJlciBvZiBwcmVkaWN0b3JzCiMnCiMnIEBwYXJhbSB5IC0gcmVzcG9uc2UgdmVjdG9yCiMnIEBwYXJhbSB4IC0gcHJlZGljdG9yIHZhcmlhYmxlcwojJyBAcGFyYW0gb3JpZyAtIGZvcmVjYXN0IG9yaWdpbgojJyBAcGFyYW0gZW5kIC0gZW5kaW5nIG9mIHZhbGlkYXRpb24gc2V0CiMnIEBwYXJhbSB0YXUgLSBWYVIgaW4gcXVlc3Rpb24KIycgQHBhcmFtIGxvd19tIC0gbG93IHZhbHVlIG9mIG0gdG8gY29uc2lkZXIKIycgQHBhcmFtIGhpZ2hfbSAtIGhpZ2ggdmFsdWUgb2YgbSB0byBjb25zaWRlcgojJwojJyBAcmV0dXJuIC0gcmV0dXJucyB0aGUgb3B0aW1hbCB2YWx1ZSBvZiBtCiMnIEBleHBvcnQKIycKIycgQGV4YW1wbGVzIC0gb3B0X20ocGNfZGZbLDFdLCBwY19kZlssLTFdLCA3NTcsIDEwMjcsIDAuMDEsIGxvd19tID0xLCBoaWdoX20gID0gNSkKb3B0X20gPSBmdW5jdGlvbih5LCB4LCBvcmlnLCBlbmQgPSBOVUxMLCB0YXUsIGxvd19tID0gMSwgaGlnaF9tLCBtb2RfZGkgPSAwLCBhcl90ZiA9IDEsIHAgPSAxLCBwcmludF9tZGwgPSAwLCBtb2RlbCA9IDEsIHJvd25hbWUgPSBOVUxMKXsKICAjIEluaXRpYWxpemUgYSBsb3NzIHZlY3RvcgogIGxvc3NfdmVjID0gcmVwKDAsaGlnaF9tLWxvd19tICsgMSkKICAjIEluaXRpYWxpemUgYW4gbSB2ZWN0b3IKICBtX3ZlYyA9IHNlcShsb3dfbSwgaGlnaF9tLCBieSA9IDEpCiAgIyBMb29wIHRocm91Z2ggYW5kIHBvcHVsYXRlIHRoZSBsb3NzIHZlY3RvcgogIGZvciAoaSBpbiAxOmxlbmd0aChsb3NzX3ZlYykpewogICAgbG9zc192ZWNbaV0gPSBxdWlldChsb3NzX2NhbGMoeT15LHg9eCxvcmlnPW9yaWcsZW5kPWVuZCwgbSA9IG1fdmVjW2ldLCB0YXUgPSB0YXUsIG1vZF9kaSA9IG1vZF9kaSwgYXJfdGYgPSBhcl90ZiwgcCA9IHAsIHByaW50X21kbCA9IHByaW50X21kbCwgbW9kZWwgPSBtb2RlbCkpW1sxXV0KICB9CiAgIyBGaW5kIHRoZSBtaW5pbWl6ZXIKICBvcHRfbSA9IHdoaWNoLm1pbihsb3NzX3ZlYykKICBvcHRfcCA9IE5BCiAgIyBDb21iaW5lIGludG8gYSBkYXRhIGZyYW1lCiAgZGYgPSBhcy5kYXRhLmZyYW1lKGNiaW5kKG9wdF9tLCBvcHRfcCkpCiAgbmFtZXMoZGYpIDwtIGMoIk9wdGltYWwgbSIsICJPcHRpbWFsIHAiKQogICMgQXNzaWduIGEgcm93bmFtZQogIGlmIChpcy5udWxsKHJvd25hbWUpID09IFRSVUUpewogICAgIyBXcml0ZSB0aGUgcm93IG5hbWVzCiAgICByb3duYW1lcyhkZikgPC0gYygiTVYgQ0FWaWFSIikKICB9CiAgZWxzZSB7CiAgICByb3duYW1lcyhkZikgPC0gcm93bmFtZQogIH0KICAjIFJldHVybiB0aGUgbG9zc192ZWN0b3IgYW5kIHRoZSBtaW5pbXplcgogIHJldHVybihsaXN0KG9wdF9tLCBsb3NzX3ZlYywgZGYpKQp9CmBgYAoKYGBge3J9CiMnIEZ1bmN0aW9uIHRoYXQgc2VsZWN0cyB0aGUgb3B0aW1hbCBudW1iZXIgb2YgbGFncwojJwojJyBAcGFyYW0geSAtIHJlc3BvbnNlIHZlY3RvcgojJyBAcGFyYW0geCAtIHByZWRpY3RvciB2YXJpYWJsZXMKIycgQHBhcmFtIG9yaWcgLSBmb3JlY2FzdCBvcmlnaW4KIycgQHBhcmFtIGVuZCAtIGVuZGluZyBvZiB2YWxpZGF0aW9uIHNldAojJyBAcGFyYW0gdGF1IC0gVmFSIGluIHF1ZXN0aW9uCiMnIEBwYXJhbSBsb3dfbSAtIGxvdyB2YWx1ZSBvZiBtIHRvIGNvbnNpZGVyCiMnIEBwYXJhbSBoaWdoX20gLSBoaWdoIHZhbHVlIG9mIG0gdG8gY29uc2lkZXIKIycKIycgQHJldHVybiAtIHJldHVybnMgdGhlIG9wdGltYWwgdmFsdWUgb2YgbQojJyBAZXhwb3J0CiMnCiMnIEBleGFtcGxlcyAtIG9wdF9tcCh5ID0gcGNfZGZbLDFdLCB4ID0gcGNfZGZbLC0xXSwgb3JpZyA9IDc1NywgZW5kID0gMTAwNywgdGF1ID0gMC4wMSwgbG93X20gPTEsIGhpZ2hfbSAgPSA1LCBsb3dfcCA9IDEsIGhpZ2hfcCA9IDEwLCBhcl90ZiA9IDIsIG1vZF9kaSA9IDEpCm9wdF9tcCA9IGZ1bmN0aW9uKHksIHgsIG9yaWcsIGVuZCA9IE5VTEwsIHRhdSwgbG93X20gPSAxLCBoaWdoX20sIGxvd19wID0gMSwgaGlnaF9wLCBtb2RfZGkgPSAwLCBhcl90ZiA9IDEsIHByaW50X21kbCA9IDAsIG1vZGVsID0gMSwgcHJpbnRfbXAgPSAwLCByb3duYW1lID0gTlVMTCl7CiAgIyBJbml0aWFsaXplIGEgbG9zcyBtYXRyaXgKICBsb3NzX21hdCA9IG1hdHJpeCgwLCBoaWdoX3AtbG93X3AgKyAxLGhpZ2hfbS1sb3dfbSArIDEpCiAgIyBJbml0aWFsaXplIGEgcCB2ZWN0b3IKICBwX3ZlYyA9IHNlcShsb3dfcCwgaGlnaF9wLCBieSA9IDEpCiAgIyBMb29wIHRocm91Z2ggYW5kIHBvcHVsYXRlIHRoZSBsb3NzIHZlY3RvcgogIGZvciAoaSBpbiAxOm5yb3cobG9zc19tYXQpKXsKICAgIGxvc3NfbWF0W2ksXSA9IG9wdF9tKHkgPSB5LCB4ID0geCwgb3JpZyA9IG9yaWcsIGVuZCA9IGVuZCwgdGF1ID0gdGF1LCBsb3dfbSA9IGxvd19tLCBoaWdoX20gID0gaGlnaF9tLCBwID0gaSwgbW9kX2RpID0gbW9kX2RpLCBhcl90ZiA9IGFyX3RmLCBwcmludF9tZGwgPSBwcmludF9tZGwsIG1vZGVsID0gbW9kZWwpW1syXV0KICB9CiAgIyBGaW5kIHRoZSBtaW5pbWl6ZXIKICBvcHRfcCA9IHdoaWNoKGxvc3NfbWF0ID09IG1pbihsb3NzX21hdCksIGFyci5pbmQgPSBUUlVFKVsxLDFdCiAgb3B0X20gPSB3aGljaChsb3NzX21hdCA9PSBtaW4obG9zc19tYXQpLCBhcnIuaW5kID0gVFJVRSlbMSwyXQogICMgUHJpbnQgdGhlIG9wdGltYWwgcCBhbmQgb3B0aW1hbCBtCiAgZGYgPSBhcy5kYXRhLmZyYW1lKGNiaW5kKG9wdF9tLCBvcHRfcCkpCiAgbmFtZXMoZGYpIDwtIGMoIk9wdGltYWwgbSIsICJPcHRpbWFsIHAiKQogICMgQXNzaWduIGEgcm93bmFtZQogIGlmIChpcy5udWxsKHJvd25hbWUpID09IFRSVUUpewogICAgaWYgKGFyX3RmID09IDEpewogICAgICAjIFdyaXRlIHRoZSByb3cgbmFtZXMKICAgICAgcm93bmFtZXMoZGYpIDwtIGMoIk1WIENBVmlhUiArIEFSIikKICAgIH0gZWxzZSBpZiAoYXJfdGYgPT0gMil7CiAgICAgICMgV3JpdGUgdGhlIHJvdyBuYW1lcwogICAgICByb3duYW1lcyhkZikgPC0gYygiTVYgQ0FWaWFSICsgU0FWIikKICAgIH0gZWxzZSBpZiAoYXJfdGYgPT0gMyl7CiAgICAgICMgV3JpdGUgdGhlIHJvdyBuYW1lcwogICAgICByb3duYW1lcyhkZikgPC0gYygiTVYgQ0FWaWFSICsgQVMiKQogICAgfSBlbHNlIHsKICAgICAgcm93bmFtZXMoZGYpIDwtIGMoIlVua25vd24gTW9kZWwiKQogICAgfQogIH0KICBlbHNlIHsKICAgIHJvd25hbWVzKGRmKSA8LSByb3duYW1lCiAgfQogICMgUHJpbnQgdGhlIGRmIGlmIHRoZSBvcHRpb24gaXMgdHVybmVkIG9uCiAgaWYgKHByaW50X21wID09IDEpewogICAgcHJpbnQoZGYpCiAgfQogICMgUmV0dXJuIHRoZSBsb3NzX3ZlY3RvciBhbmQgdGhlIG1pbmltemVyCiAgcmV0dXJuKGxpc3Qob3B0X20sIG9wdF9wLCBsb3NzX21hdCwgZGYpKQp9CmBgYAoKCmBgYHtyfQojJyBBIGZ1bmN0aW9uIHRoYXQgY29tYmluZXMgb3B0aW1hbCB2YWx1ZXMgb2YgbSBhbmQgcCBpbnRvIGEgZmluYWwgdGFibGUKIycKIycgQHBhcmFtIG0xIC0gdGhlIGRhdGEgZnJhbWUgZnJvbSB0aGUgIk1WIENBVmlhUiIgcnVuCiMnIEBwYXJhbSBtMiAtIHRoZSBkYXRhIGZyYW1lIGZyb20gdGhlICJNViBDQVZpYVIgKyBBUiIgcnVuCiMnIEBwYXJhbSBtMyAtIHRoZSBkYXRhIGZyYW1lIGZyb20gdGhlICJNViBDQVZpYVIgKyBTQVYiIHJ1bgojJyBAcGFyYW0gbTQgLSB0aGUgZGF0YSBmcmFtZSBmcm9tIHRoZSAiTVYgQ0FWaWFSICsgQVMiIHJ1bgojJwojJyBAcmV0dXJuIC0gYSBuaWNlbHkgZm9ybWF0dGVkIHRhYmxlCiMnIEBleHBvcnQKIycKIycgQGV4YW1wbGVzIC0gcHJldHR5X3BtKG9wdF9wcmVkX25sW1szXV0sIG9wdF9wbV9tMVtbNF1dLCBvcHRfcG1fbTJbWzRdXSwgb3B0X3BtX20zW1s0XV0pCnByZXR0eV9wbSA9IGZ1bmN0aW9uKG0xLCBtMiwgbTMsIG00KXsKICAjIE1lcmdlIHRoZSBpbmRpdmlkdWFsIGRhdGEgZnJhbWVzCiAgcG1fcHJldHR5X2RmID0gcmJpbmQobTEsIG0yLCBtMywgbTQpCiAgIyBGb3JtYXQgbmljZWx5CiAgcG1fcHJldHR5X2RmICU+JSBrYWJsZShjYXB0aW9uID0gIk9wdGltYWwgTnVtYmVyIG9mIERpZmZ1c2lvbiBJbmRpY2VzIChtKSBhbmQgTGFncyAocCkgZm9yIERpZmZlcmVudCBNb2RlbHMiLCBkaWdpdHMgPSAwKSAlPiUga2FibGVfc3R5bGluZygic3RyaXBlZCIsIGZ1bGxfd2lkdGggPSBGKSAlPiUga2FibGVfc3R5bGluZygpICU+JSBmb290bm90ZShnZW5lcmFsID0gIlRoZSBNViBDQVZpYVIgbW9kZWwgZG9lc24ndCBoYXZlIGFuIG9wdGltYWwgdmFsdWUgZm9yIHAgYmVjYXVzZSB0aGVyZSBhcmUgbm8gQVIgbGFncyBpbiB0aGUgbW9kZWwiCiAgKQogIAp9CgpgYGAKCgpgYGB7cn0KIycgSGVyZSBpcyBhIGZ1bmN0aW9uIHRoYXQgcnVucyB0aGUgdW5pdmFyaWF0ZSBDQVZpYVIgbW9kZWwgNCB0aW1lcwojJwojJyBAcGFyYW0gZGYgLSB0aGUgcGVyY2VudCBjaGFuZ2UgZGF0YSBmcmFtZSB0byBjb25zaWRlcgojJyBAcGFyYW0gbmZjc3QgLSBudW1iZXIgb2YgZm9yZWNhc3RzIHRvIHJ1bgojJyBAcGFyYW0gdGF1IC0gdGhlIFZhUiBsZXZlbCB0byBjb25zaWRlcgojJyBAcGFyYW0gbm9fcnVuIC0gc3BlY2lmaWVzIGlmIGFueSBtb2RlbHMgc2hvdWxkIG5vdCBiZSBydW4KIycKIycgQHJldHVybiAtIGEgbGlzdCBvZiB0aGUgNCB1bml2YXJpYXRlIG1vZGVsIGZvcmVjYXN0cwojJyBAZXhwb3J0CiMnCiMnIEBleGFtcGxlcyAtIGFjZWcgPSBnZW5fdXZfdGVzdChwY19kZiwgMSwgMC4wNSwgbm9fcnVuID0gYygxLDEsMCwxKSkKZ2VuX3V2X3Rlc3QgPSBmdW5jdGlvbihkZiwgbmZjc3QsIHRhdSwgbm9fcnVuID0gYygwLDAsMCwwKSl7CiAgIyBtb2RlbCB0eXBlICgxIC0gU0FWLCAyIC0gQVMsIDMgLSBHQVJDSCwgNCAtIEFEQVBUSVZFKSAKICAjIEluaXRpYWxpemUgYSBsaXN0ICAKICBvdXRfbGlzdCA9IGxpc3QoKQogICMgUnVuIHRoZSBmb3VyIG1vZGVscyAtIG1vZGVsIDE7IFNBVgogIGlmIChub19ydW5bMV0gPT0gMCl7CiAgICB1dmNhdl8xID0gcm9sbGluZ19wcmVkaWN0aW9ucyhkZlssMV0sIHJhbmdlX2RhdGEgPSAoMTpsZW5ndGgoZGZbLDFdKSksIG5mY3N0ID0gbmZjc3QsIG1vZGVsID0gMSwgRyA9IDEwLCBjb2wgPSAxLCBsZXZlbCA9IHRhdSkKICB9CiAgIyBBZGQgYSBmaWxsZXIgaWYgdGhlcmUncyBubyBlbnRyeQogIGVsc2UgewogICAgdXZjYXZfMSA9IDAKICB9CiAgIyBNb2RlbCAyIC0gQVMKICBpZiAobm9fcnVuWzJdID09IDApewogICAgdXZjYXZfMiA9IHJvbGxpbmdfcHJlZGljdGlvbnMoZGZbLDFdLCByYW5nZV9kYXRhID0gKDE6bGVuZ3RoKGRmWywxXSkpLCBuZmNzdCA9IG5mY3N0LCBtb2RlbCA9IDIsIEcgPSAxMCwgY29sID0gMSwgbGV2ZWwgPSB0YXUpCiAgfQogIGVsc2UgewogICAgdXZjYXZfMiA9IDAKICB9CiAgIyBNb2RlbCAzIC0gR0FSQ0gKICBpZiAobm9fcnVuWzNdID09IDApewogICAgdXZjYXZfMyA9IHJvbGxpbmdfcHJlZGljdGlvbnMoZGZbLDFdLCByYW5nZV9kYXRhID0gKDE6bGVuZ3RoKGRmWywxXSkpLCBuZmNzdCA9IG5mY3N0LCBtb2RlbCA9IDMsIEcgPSAxMCwgY29sID0gMSwgbGV2ZWwgPSB0YXUpCiAgfQogIGVsc2UgewogICAgdXZjYXZfMyA9IDAKICB9CiAgIyBNb2RlbCA0IC0gQWRhcHRpdmUKICBpZiAobm9fcnVuWzRdID09IDApewogICAgdXZjYXZfNCA9IHJvbGxpbmdfcHJlZGljdGlvbnMoZGZbLDFdLCByYW5nZV9kYXRhID0gKDE6bGVuZ3RoKGRmWywxXSkpLCBuZmNzdCA9IG5mY3N0LCBtb2RlbCA9IDQsIEcgPSAxMCwgY29sID0gMSwgbGV2ZWwgPSB0YXUpCiAgfQogIGVsc2UgewogICAgdXZjYXZfNCA9IDAKICB9CiAgIyBFeHBvcnQgdGhlIGRhdGEgYXMgYSBsaXN0CiAgcmV0dXJuKGxpc3QodXZjYXZfMSwgdXZjYXZfMiwgdXZjYXZfMywgdXZjYXZfNCkpCn0KCmBgYAoKYGBge3J9CiMnIEZ1bmN0aW9uIHRvIHBsb3QgdGhlIGRhdGEgd2hpY2ggd2UgZ2VuZXJhdGUgaW4gcHJldmlvdXMgZnVuY3Rpb25zCiMnCiMnIEBwYXJhbSBwbG90X21hdHJpeCAtIG1hdHJpeCB3aXRoIHRoZSBkYXRhIHRvIHBsb3QKIycgQHBhcmFtIG5vcm1fdmFsdWUgLSB3aGF0IHRvIHN1YnRhY3QgZnJvbSB0aGUgZGF0YSB0byBtYWtlIGl0IG9uIGEgcGVyY2VudGFnZSBjaGFuZ2UgYmFzaXMuIERlZmF1bHQgaXMgMTAwLgojJwojJyBAcmV0dXJuIAojJyBAZXhwb3J0IC0gYSBwbG90IG9mIHRoZSBkYXRhIGJ5IGRpZmZ1c2lvbiBpbmRleCBudW1iZXIKIycKIycgQGV4YW1wbGVzID0gcGx0X2RhdGEocGxvdF9tdHhbWzFdXSksIGFiYyA9IHBsdF9kYXRhKHBsb3RfbWF0LCB0YXUgPSAwLjAxKQpwbHRfZGF0YSA9IGZ1bmN0aW9uKHBsb3RfbWF0cml4LCB0YXUsIHJlc3BfdmFyLCBudGVzdCl7CiAgIyBFc3RhYmxpc2ggYSBtYXhpbXVtIGFuZCBtaW5pbXVtIHZhbHVlCiAgbWF4X3ZhbCA9IG1heChwbG90X21hdHJpeFssMTpuY29sKHBsb3RfbWF0cml4KV0pCiAgbWluX3ZhbCA9IG1pbihwbG90X21hdHJpeFssMTpuY29sKHBsb3RfbWF0cml4KV0pCiAgIyBDYWxjdWxhdGUgaW5pdGFsIGFuZCBlbmRpbmcgdGltZSB2YWx1ZQogIHN0YXJ0ID0gaW5kZXgocGxvdF9tYXRyaXgpWzFdCiAgZW5kID0gaW5kZXgocGxvdF9tYXRyaXgpW25yb3cocGxvdF9tYXRyaXgpXQogIGluZF92YWxzID0gaW5kZXgocGxvdF9tYXRyaXgpIC0gc3RhcnQKICAjIENyZWF0ZSBhbiBpbml0aWFsIHBsb3QgYW5kIGFkZCBsaW5lcwogICAgZm9yIChpIGluIDE6bmNvbChwbG90X21hdHJpeCkpewogICAgICBpZiAoaSA9PSAxKXsKICAgICAgICAjIDQvMi8yMDIwIC0gZml4aW5nIHRoZSBpbmRleAogICAgICAgIHBsb3QudHMoaW5kX3ZhbHMscGxvdF9tYXRyaXhbLGldLCB0eXBlID0gImwiLCB4bGFiID0gcGFzdGUoIkRheXMgU2luY2UiLCBhcy5EYXRlKHN0YXJ0KSksIHlsYWIgPSAiUGVyY2VudCBDaGFuZ2UgaW4gUEciLCB5bGltID0gYyhtaW5fdmFsLG1heF92YWwpLCBsd2QgPSAxLCBtYWluID0gcGFzdGUoIlByZWRpY3RpbmciLCByZXNwX3ZhciwgIlJldHVybnMgZnJvbSIsIGFzLkRhdGUoc3RhcnQpLCAidG8iLCBhcy5EYXRlKGVuZCkpLCBzdWIgPSBwYXN0ZSgiVGhlIFZhUiBMZXZlbCBpcyAiLCAxMDAqdGF1LCAiJSIsICI7IFRoZXJlIGFyZSAiLCBudGVzdCwgIiBUcmFkaW5nIERheXMgUGxvdHRlZCBBYm92ZSIsIHNlcCA9ICIiKSkKICAgICAgICAjIHBsb3QudHMoaW5kZXgocGxvdF9tYXRyaXgpLCBwbG90X21hdHJpeFssaV0sIHR5cGUgPSAibCIsIHhsYWIgPSAiVHJhZGluZyBEYXlzIiwgeWxhYiA9ICJQZXJjZW50IENoYW5nZSBpbiBQRyIsIHlsaW0gPSBjKG1pbl92YWwsbWF4X3ZhbCksIGx3ZCA9IDEsIG1haW4gPSAiUHJlZGljdGluZyBQRyBSZXR1cm5zIE92ZXIgTGFzdCAyNTAgVHJhZGluZyBEYXlzIGluIDIwMDgiLCBzdWIgPSBwYXN0ZSgiVGhlIFZhUiBMZXZlbCBpcyAiLCAxMDAqdGF1LCAiJSIsIHNlcCA9ICIiKSkKICAgIH0gZWxzZSBpZihpICVpbiUgc2VxKDIsOCwxKSkgewogICAgICAgIGxpbmVzKGluZF92YWxzLHBsb3RfbWF0cml4WyxpXSwgY29sID0gaS0xLCBsdHkgPSAyKQogICAgfSBlbHNlIHsKICAgICAgICBsaW5lcyhpbmRfdmFscyxwbG90X21hdHJpeFssaV0sIGNvbCA9IGktMSwgbHR5ID0gMiwgbHdkID0gMikKICAgIH0KICAgIH0KICAjIERlZmluZSBhIHNlcXVlbmNlIGZvciBwbG90dGluZwogIHBsb3Rfc2VxID0gc2VxKDEsIG5jb2wocGxvdF9tYXRyaXgpKQogIGxlZ2VuZCgidG9wbGVmdCIsIGxlZ2VuZCA9IGMoY29sbmFtZXMocGxvdF9tYXRyaXgpKSwgY29sID0gcGxvdF9zZXEsIGx0eSA9IGMoMSwgcmVwKDIsIDcpLCByZXAoMywgaWZlbHNlKG5jb2wocGxvdF9tYXRyaXgpLTggPD0gMCwgMCwgbmNvbChwbG90X21hdHJpeCktOCkpKSwgbHdkID0gYygxLCByZXAoMSwgNyksIHJlcCgyLCBpZmVsc2UobmNvbChwbG90X21hdHJpeCktOCA8PSAwLCAwLCBuY29sKHBsb3RfbWF0cml4KS04KSkpKQogICMgQWRkIGEgbGluZSBmb3IgMAogICMgYWJsaW5lKGggPSAwLCBjb2wgPSAiYmxhY2siLCBsdHkgPSAyKQp9CgoKYGBgCgpgYGB7cn0KIycgQSBmdW5jdGlvbiB0byBjYWxjdWxhdGUgbG9zc2VzIGJhc2VkIG9uIHRoZSB0ZXN0IHNhbXBsZQojJwojJyBAcGFyYW0gdHJ1ZV92ZWMgLSB0aGUgdHJ1ZSB2ZWN0b3Igb2YgcmV0dXJucwojJyBAcGFyYW0gcHJlZF92ZWMgLSB0aGUgcHJlZGljdGVkIHZlY3RvciBmcm9tIHRoZSBtb2RlbCBydW5zCiMnIEBwYXJhbSB0YXUgLSBWYVIgbGV2ZWwuIE11c3QgbWF0Y2ggd2hhdCB0aGUgbW9kZWwgdXNlZAojJwojJyBAcmV0dXJuIC0gdG90YWwgbG9zc2VzIGFuZCB0aGUgZW50aXJlIGxvc3MgdmVjdG9yCiMnIEBleHBvcnQKIycKIycgQGV4YW1wbGVzCmxvc3NfdGVzdCA9IGZ1bmN0aW9uKHRydWVfdmVjLCBwcmVkX3ZlYywgdGF1KXsKICAjIEluaXRpYWxpemUgYSBsb3NzIHZlY3RvcgogIGx2ZWMgPSByZXAoMCwgbGVuZ3RoKHRydWVfdmVjKSkKICAjIEluaXRpYWxpemUgYSBicmVhayB2ZWN0b3IgdG8gc2VlIHdoZW4gVmFSIGlzIGJyb2tlbgogIGJ2ZWMgPSByZXAoMCwgbGVuZ3RoKHRydWVfdmVjKSkKICBmb3IgKGkgaW4gMTpsZW5ndGgodHJ1ZV92ZWMpKXsKICAgICMgQ2FsY3VsYXRlIGFuIGluZGljYXRvciB2YXJpYWJsZQogICAgYnZlY1tpXSA9IGlmZWxzZSh0cnVlX3ZlY1tpXSA8IHByZWRfdmVjW2ldLCAxLDApCiAgICAjIFVzZSBpbmRpY2F0b3IgaW4gZnVuY3Rpb24gYmVsb3cKICAgIGx2ZWNbaV0gPSAodGF1IC0gYnZlY1tpXSkqKHRydWVfdmVjW2ldIC0gcHJlZF92ZWNbaV0pCiAgfQogICMgQWRkIHVwIHRoZSBsb3NzZXMKICAjIHN1bWxvc3MgPSBzdW0obHZlYykvbGVuZ3RoKGx2ZWMpCiAgc3VtbG9zcyA9IHN1bShsdmVjKQogICMgQWRkIHVwIHRoZSBWYVIgYnJlYWthZ2UKICB2YXJicmVhayA9IHN1bShidmVjKS9sZW5ndGgoYnZlYykKICByZXR1cm4obGlzdChzdW1sb3NzLGx2ZWMsIHZhcmJyZWFrLCBidmVjKSkKfQpgYGAKCgoKYGBge3J9CiMnIEEgZnVuY3Rpb24gdG8gY2FsY3VsYXRlIGxvc3NlcyBiYXNlZCBvbiB0aGUgcGxvdCBtYXRyaXgKIycKIycgQHBhcmFtIGRhdGFfbWF0IC0gYSBtYXRyaXggb2YgZm9yZWNhc3RlZCBWYVIgdmFsdWVzLCB3aXRoIHRoZSB0cnVlIHZhbHVlIGluIHRoZSBmaXJzdCBjb2x1bW4KIycgQHBhcmFtIHRhdSAtIFZhUiBsZXZlbC4gTXVzdCBtYXRjaCB3aGF0IHRoZSBtb2RlbCB1c2VkCiMnCiMnIEByZXR1cm4gLSBhIGxpc3Qgb2YgZm91ciBpdGVtcy4gCiMnIDEgPSBhIHZlY3RvciBvZiB0aGUgbG9zc2VzIG9mIGFsbCBtb2RlbHMuIAojJyAyID0gYSB2ZWN0b3Igc2hvd2luZyB0aGUgcGVyY2VudGFnZSBvZiBWYVIgYnJlYWtzIGJ5IG1vZGVsCiMnIDMgPSB0aGUgbG9zcyBtYXRyaXgKIycgNCA9IHRoZSBicmVhayBtYXRyaXgKIycgQGV4cG9ydAojJwojJyBAZXhhbXBsZXMKZ2VuX2xvc3NfdGVzdCA9IGZ1bmN0aW9uKGRhdGFfbWF0LCB0YXUpewogICMgSW5pdGlhbGl6ZSBsb3NzIGFuZCBicmVhayBtYXRyaWNlcwogIGxtYXQgPSBibWF0ID0gbWF0cml4KDAsIG5yb3cgPSBucm93KGRhdGFfbWF0KSwgbmNvbCA9IG5jb2woZGF0YV9tYXQpLTEpCiAgIyBidmVjID0gcmVwKDAsIGxlbmd0aCh0cnVlX3ZlYykpCiAgIyBQb3B1bGF0ZSB0aGUgbWF0cmljZXMKICBmb3IgKGkgaW4gMTpucm93KGxtYXQpKXsKICAgIGZvciAoaiBpbiAxOihuY29sKGxtYXQpKSl7CiAgICAgICMgQ2FsY3VsYXRlIGFuIGluZGljYXRvciB2YXJpYWJsZQogICAgICBibWF0W2ksal0gPSBpZmVsc2UoZGF0YV9tYXRbaSwxXSA8IGRhdGFfbWF0W2ksaisxXSwgMSwwKQogICAgICAjIFVzZSBpbmRpY2F0b3IgaW4gZnVuY3Rpb24gYmVsb3cKICAgICAgbG1hdFtpLGpdID0gKHRhdSAtIGJtYXRbaSxqXSkqKGRhdGFfbWF0W2ksMV0gLSBkYXRhX21hdFtpLGorMV0pCiAgICB9ICAgIAogIH0KICAjIEFkZCB1cCB0aGUgbG9zc2VzCiAgc3VtbG9zcyA9IGNvbFN1bXMobG1hdCkKICAjIEFkZCB1cCB0aGUgVmFSIGJyZWFrYWdlCiAgdmFyYnJlYWsgPSBjb2xTdW1zKGJtYXQpL25yb3coYm1hdCkKICByZXR1cm4obGlzdChzdW1sb3NzLCB2YXJicmVhaywgbG1hdCwgYm1hdCkpCn0KYGBgCgoKCmBgYHtyfQojJyBBIGZ1bmN0aW9uIHRvIG1ha2UgYSBuaWNlIGNvbXBhcmlzb24gb2YgbG9zc2VzCiMnCiMnIEBwYXJhbSBkYXRhX21hdCAtIGlucHV0IGRhdGEgbWF0cml4IHVzZWQgaW4gdGhlIGNhbGN1bGF0aW9uIG9mIGxvc3NlcwojJyBAcGFyYW0gbG9zc19saXN0IC0gYSBsaXN0IG9mIHRoZSBsb3NzZXMgY2FsY3VsYXRlZCBmcm9tIHRoZSBDQVZpYVIgZnVuY3Rpb24KIycgQHBhcmFtIHRhdSAtIHRoZSByaXNrIGxldmVsIHVzZWQKIycgQHBhcmFtIG50ZXN0IC0gdGhlIG51bWJlciBvZiB0ZXN0IHBvaW50cwojJwojJyBAcmV0dXJuCiMnIEBleHBvcnQgLSByZXR1cm5zIGEgbmljZWx5IGZvcm1hdHRlZCB0YWJsZQojJwojJyBAZXhhbXBsZXMgLSBwcmV0dHlfdGFibGVzKHBsb3RfbWF0LCBsX2xpc3QsIHRhdSA9IDAuMDEpCnByZXR0eV90YWJsZXMgPSBmdW5jdGlvbihkYXRhX21hdCwgbG9zc19saXN0LCB0YXUsIG50ZXN0KXsKICAjIENvbWJpbmUgaW50byBhIGRhdGEgZnJhbWUKICBkZiA9IGFzLmRhdGEuZnJhbWUocmJpbmQobG9zc19saXN0W1sxXV0sIGxvc3NfbGlzdFtbMl1dKSkKICAjIENhbGN1bGF0ZSBpbml0YWwgYW5kIGVuZGluZyB0aW1lIHZhbHVlCiAgc3RhcnQgPSBpbmRleChkYXRhX21hdClbMV0KICBlbmQgPSBpbmRleChkYXRhX21hdClbbnJvdyhkYXRhX21hdCldCiAgIyBBZGQgcm93L2NvbHVtbiBuYW1lcwogIGNvbG5hbWVzKGRmKSA8LSBjb2xuYW1lcyhkYXRhX21hdFssLTFdKQogIHJvd25hbWVzKGRmKSA8LSBjKCJMb3NzZXMiLCAiVmFSIEJyZWFrcyAoJSkiKQogICMgQ29udmVydCB0byBhIHRhYmxlCiAgZGYgJT4lIGthYmxlKGNhcHRpb24gPSBwYXN0ZSgiQ29tcGFyaXNvbiBvZiBWYVIgTWV0aG9kcyBmb3IgYSAiLCB0YXUqMTAwLCAiJSBWYVIiLCBzZXAgPSAiIiksIGRpZ2l0cyA9IDMpICU+JSBrYWJsZV9zdHlsaW5nKCJzdHJpcGVkIiwgZnVsbF93aWR0aCA9IEYpICU+JSBrYWJsZV9zdHlsaW5nKCkgJT4lIGZvb3Rub3RlKGdlbmVyYWwgPSBwYXN0ZSgiQ2FsY3VsYXRlZCB1c2luZyIsIG50ZXN0LCAidHJhZGluZyBkYXlzIGZyb20iLCBhcy5EYXRlKHN0YXJ0KSwgInRvIiwgYXMuRGF0ZShlbmQpKSkKfQpgYGAKCmBgYHtyfQojJyBBIGRyZXNzZWQgdXAgdmVyc2lvbiBvZiB0aGUgZXhwb3J0IGZ1bmN0aW9uCiMnCiMnIEBwYXJhbSB2YXJfZmlsZSAtIGZpbGUgdG8gZXhwb3J0CiMnIEBwYXJhbSBwYXRoIC0gZmlsZXBhdGgKIycgQHBhcmFtIGZpbGVuYW1lIC0gbmFtZSBvZiB0aGUgZmlsZSwgZW5kaW5nIHdpdGggLkNTVgojJwojJyBAcmV0dXJuCiMnIEBleHBvcnQgLSBleHBvcnRlZCBDU1YgZmlsZQojJwojJyBAZXhhbXBsZXMgLSBleHBfZnVuYyh2YXJfZmlsZSA9IHZhcl8xcGNfMjAxNl91c2V0ZltbMV1dLCBwYXRoID0gIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfVVNfRVRGX3J1bnMvIiwgZmlsZW5hbWUgPSAiVEVTVC5jc3YiKQpleHBfZnVuYyA9IGZ1bmN0aW9uKHZhcl9maWxlLCBwYXRoLCBmaWxlbmFtZSl7CiAgIyBXcml0ZSBhIHpvbwogIHdyaXRlLnpvbyh2YXJfZmlsZSwgcGFzdGUwKHBhdGgsIGZpbGVuYW1lKSwgcXVvdGUgPSBGQUxTRSwgc2VwID0gIiwiKQp9CgojIGV4cF9mdW5jKHZhcl9maWxlID0gdmFyXzFwY18yMDE2X3VzZXRmW1sxXV0sIHBhdGggPSAiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9VU19FVEZfcnVucy8iLCBmaWxlbmFtZSA9ICJURVNULmNzdiIpCgpgYGAKCgoKCiMgQmlnIFNpbXVsYXRpb24gRnVuY3Rpb24KCmBgYHtyfQojJyBUaGlzIGlzIHRoZSAibWFzdGVyIiBmdW5jdGlvbiB3aGVyZSB3ZSdsbCBldmFsdWF0ZSB0aGUgaW1wb3J0YW5jZSBvZiB0aGUgVmFSIG1vZGVsIG92ZXIgc2V2ZXJhbCB0aW1lIHBlcmlvZHMKIycKIycgQHBhcmFtIHN5bWJvbF9saXN0IC0gYSBsaXN0IG9mIHN5bWJvbHMgdG8gZmVlZCBpbnRvIHRoZSBtb2RlbCAKIycgQHBhcmFtIHJlc3BfdmFyIC0gdGhlIHJlc3BvbnNlIHZhcmlhYmxlCiMnIEBwYXJhbSBjb21wbF9jYXNlIC0gc2hvdWxkIHRoZSBtb2RlbCByZXF1aXJlIGNvbXBsZXRlIGNhc2VzPyBEZWZhdWx0IHZhbHVlIGlzIDEuCiMnIEBwYXJhbSBhZGpfY2xvc2UgLSB1c2UgYWRqdXN0ZWQgY2xvc2UgcHJpY2UgZm9yIHRoZSBwcmVkaWN0b3JzPyBEZWZhdWx0IHZhbHVlIGlzIDEuCiMnIEBwYXJhbSByZXNwX2Fkal9jbG9zZSAtIHVzZSBhZGp1c3RlZCBjbG9zZSBwcmljZSBmb3IgdGhlIHJlc3BvbnNlPyBEZWZhdWx0IHZhbHVlIGlzIDEuCiMnIEBwYXJhbSBzdGFydF9kYXRlIC0gc3RhcnQgZGF0ZSB0byBwdWxsIGRhdGEgZnJvbQojJyBAcGFyYW0gZW5kX2RhdGUgLSBlbmQgZGF0ZSB0byBwdWxsIGRhdGEgZnJvbQojJyBAcGFyYW0gbnZhbCAtIG51bWJlciBvZiB2YWxpZGF0aW9uIHBvaW50cyB0byB1c2UKIycgQHBhcmFtIG50ZXN0IC0gbnVtYmVyIG9mIHRlc3QgcG9pbnRzIHRvIHVzZQojJyBAcGFyYW0gdGF1IC0gVmFSIGxldmVsIHRvIHVzZQojJyBAcGFyYW0gbG93X20gLSBsb3cgbnVtYmVyIG9mIHByZWRpY3RvcnMgdG8gdGVzdAojJyBAcGFyYW0gaGlnaF9tICAtIGxvdyBudW1iZXIgb2YgcHJlZGljdG9ycyB0byB0ZXN0CiMnIEBwYXJhbSB1dl9saXN0IC0gYSBsaXN0IG9mIGEgcHJlLXJ1biB1bml2YXJpYXRlIG1vZGVsLiBJZiBhIGRhdGEgZnJhbWUgaXMgbm90IHByb3ZpZGVkLCB0aGUgbGVuZ3RoeSB1diBtb2RlbCB3aWxsIHJ1biAKIycgQHBhcmFtIG5vX3J1biAtIHRoaW5ncyBub3QgdG8gcnVuIGluIHRoZSBtb2RlbAojJyBAcGFyYW0gbG93X3AgLSBsb3cgdmFsdWUgZm9yIG51bWJlciBvZiBsYWdzCiMnIEBwYXJhbSBoaWdoX3AgLSBoaWdoIHZhbHVlIGZvciBudW1iZXIgb2YgbGFncwojJyBAcGFyYW0gbmFfaW50ZXJwIC0gc2hvdWxkIHRoZSBmdW5jdGlvbiBpbnRlcnBvbGF0ZSBOQSdzCiMnIEBwYXJhbSBwcmludF9tZGwgLSBwcmludCB0aGUgbW9kZWwgc3VtbWFyaWVzPwojJyBAcGFyYW0gcHJpbnRfbXAgLSBwcmludCB0aGUgb3B0aW1hbCB2YWx1ZXMgZm9yIHAgYW5kIG0KIycgQHBhcmFtIGxhZ19wcmVkIC0gZG8geW91IHdhbnQgdG8gbGFnIHRoZSBtIHByZWRpY3RvcnMgKGRlZmF1bHQgaXMgMTsgc3Ryb25nbHkgcmVjb21tZW5kZWQpCiMnIEBwYXJhbSByb3duYW1lIC0gd2hhdCB0byBuYW1lIHRoZSByb3dzIG9mIHRoZSBuaWNlIHAgYW5kIG0gbWF0cml4CiMnIEBwYXJhbSBleHBvcnRfY3N2IC0gZG8geW91IHdhbnQgdG8gZXhwb3J0IGEgQ1NWPyBEZWZhdWx0IGlzIDEuCiMnIEBwYXJhbSBwYXRoIC0gcGF0aCB0byBleHBvcnQgdGhlIENTVgojJyBAcGFyYW0gZmlsZW5hbWUgLSB3aGF0IHRvIG5hbWUgdGhlIENTVgojJwojJyBAcmV0dXJuIC0gYSBsaXN0IG9mIHRoZSBwbG90IG1hdHJpeCwgYSBwbG90LCBhIGxpc3Qgd2l0aCBsb3NzZXMsIGFuZCBhIHRhYmxlCiMnIEBleHBvcnQgLSBhIHBsb3QgYW5kIGEgdGFibGUKIycKIycgQGV4YW1wbGVzIC0gY2F2X3NpbXVsKGMoIkRJUyIsICJHRSIsICJJQk0iLCAiTU1NIiwgIlhPTSIpLCByZXNwX3ZhciA9ICJQRyIsIHN0YXJ0X2RhdGUgPSAiMjAwNC0wMS0wMSIsIGVuZF9kYXRlID0gIjIwMDgtMTItMzEiLCBudmFsID0gMjUwLCBudGVzdCA9IDI1MCwgbG93X20gPSAxLCBoaWdoX20gPSA1LCB0YXUgPSAwLjAxLCB1dl9saXN0ID0gdXZfY2F2X2xpc3QpCmNhdl9zaW11bCA9IGZ1bmN0aW9uKHN5bWJvbF9saXN0LCByZXNwX3ZhciwgY29tcGxfY2FzZSA9IDEsIGFkal9jbG9zZSA9IDEsIHJlc3BfYWRqX2Nsb3NlID0gMSwgc3RhcnRfZGF0ZSA9ICIxOTAwLTAxLTAxIiwgZW5kX2RhdGUgPSBTeXMuRGF0ZSgpLCBudmFsLCBudGVzdCwgdGF1LCBsb3dfbSA9IDEsIGhpZ2hfbSwgbG93X3AgPSAxLCBoaWdoX3AsIHV2X2xpc3QgPSBOVUxMLCBub19ydW4gPSBjKDAsMCwwLDApLCBuYV9pbnRlcnAgPSBUUlVFLCBwcmludF9tZGwgPSAwLCBwcmludF9tcCA9IDAsIGxhZ19wcmVkID0gMSwgcm93bmFtZSA9IE5VTEwsIGV4cG9ydF9jc3YgPSAxLCBwYXRoLCBmaWxlbmFtZSl7CiAgIyBTZWxlY3QgZGF0YSBwYXJhbWV0ZXJzLCBwdWxsIHRoZSBkYXRhLCBhbmQgcGVyY2VudCBjaGFuZ2UgdGhlIGRhdGEKICBkZiA9IGRpZmZfaW5kZXhfZGYoc3ltYm9sX2xpc3QgPSBzeW1ib2xfbGlzdCwgcmVzcF92YXIgPSByZXNwX3ZhciwgY29tcGxfY2FzZSA9IGNvbXBsX2Nhc2UsIGFkal9jbG9zZSA9IGFkal9jbG9zZSwgcmVzcF9hZGpfY2xvc2UgPSByZXNwX2Fkal9jbG9zZSwgc3RhcnRfZGF0ZSA9IHN0YXJ0X2RhdGUsIGVuZF9kYXRlID0gZW5kX2RhdGUsIGxhZ19wcmVkID0gbGFnX3ByZWQpCiAgIyBUYWtlIHRoZSBwZXJjZW50IGNoYW5nZSBvZiB0aGUgZGF0YQogIHBjX2RmID0gcGNfZGlmZl9pbmRleChkZikKICAjIEV4dHJhY3QgdGhlIGxlZ250aCBvZiB0aGUgZGF0YSBmcmFtZQogIG5yID0gdGVzdF9lbmQgPSBucm93KHBjX2RmKQogICMgQ2FsY3VsYXRlIHRoZSBzdGFydCBvZiB0aGUgdmFsIHBlcmlvZCwgdGhlIGVuZCBvZiB0aGUgdmFsIHBlcmlvZCwgYW5kIHRoZSBiZWdpbm5pbmcgYW5kIGVuZCBvZiB0ZXN0IHBlcmlvZAogIHRlc3Rfb3JpZyA9IHRlc3RfZW5kIC0gbnRlc3QKICB2YWxfZW5kID0gdGVzdF9vcmlnCiAgdmFsX29yaWcgPSB0ZXN0X29yaWcgLSBudmFsCiAgIyBUZXN0IGZvciB0aGUgb3B0aW1hbCBudW1iZXIgb2YgcGFyYW1ldGVycwogIG9wdF9wcmVkX25sID0gb3B0X20oeSA9IHBjX2RmWywxXSwgeCA9IHBjX2RmWywtMV0sIG9yaWcgPSB2YWxfb3JpZywgZW5kID0gdmFsX2VuZCwgdGF1ID0gdGF1LCBsb3dfbSA9IGxvd19tLCBoaWdoX20gPSBoaWdoX20sIHJvd25hbWUgPSByb3duYW1lKQogIG9wdF9wcmVkX2FydDEgPSBvcHRfbXAoeSA9IHBjX2RmWywxXSwgeCA9IHBjX2RmWywtMV0sIG9yaWcgPSB2YWxfb3JpZywgZW5kID0gdmFsX2VuZCwgdGF1ID0gdGF1LCBsb3dfbSA9IGxvd19tLCBoaWdoX20gPSBoaWdoX20sIGxvd19wID0gbG93X3AsIGhpZ2hfcCA9IGhpZ2hfcCxtb2RfZGkgPSAxLCBhcl90ZiA9IDEsIHByaW50X21kbCA9IHByaW50X21kbCwgcHJpbnRfbXAgPSBwcmludF9tcCwgcm93bmFtZSA9IHJvd25hbWUpCiAgb3B0X3ByZWRfYXJ0MiA9IG9wdF9tcCh5ID0gcGNfZGZbLDFdLCB4ID0gcGNfZGZbLC0xXSwgb3JpZyA9IHZhbF9vcmlnLCBlbmQgPSB2YWxfZW5kLCB0YXUgPSB0YXUsIGxvd19tID0gbG93X20sIGhpZ2hfbSA9IGhpZ2hfbSwgbG93X3AgPSBsb3dfcCwgaGlnaF9wID0gaGlnaF9wLG1vZF9kaSA9IDEsIGFyX3RmID0gMiwgcHJpbnRfbWRsID0gcHJpbnRfbWRsLCBwcmludF9tcCA9IHByaW50X21wLCByb3duYW1lID0gcm93bmFtZSkKICBvcHRfcHJlZF9hcnQzID0gb3B0X21wKHkgPSBwY19kZlssMV0sIHggPSBwY19kZlssLTFdLCBvcmlnID0gdmFsX29yaWcsIGVuZCA9IHZhbF9lbmQsIHRhdSA9IHRhdSwgbG93X20gPSBsb3dfbSwgaGlnaF9tID0gaGlnaF9tLCBsb3dfcCA9IGxvd19wLCBoaWdoX3AgPSBoaWdoX3AsIG1vZF9kaSA9IDEsIGFyX3RmID0gMywgcHJpbnRfbWRsID0gcHJpbnRfbWRsLCBwcmludF9tcCA9IHByaW50X21wLCByb3duYW1lID0gcm93bmFtZSkKICAjIGdlbl91dl90ZXN0KHBjX2RmLCAxLCAwLjA1LCBub19ydW4gPSBjKDEsMSwwLDEpKQogICMgVXNlIHRoZSBhYm92ZSBmb3JlY2FzdHMgdG8gaW5wdXQgaW50byB0aGUgYWJvdmUKICBtdl9mY3N0ID0gbW9kX2RpKHBjX2RmWywxXSwgcGNfZGZbLC0xXSwgb3JpZyA9IHRlc3Rfb3JpZywgbSA9IG9wdF9wcmVkX25sW1sxXV0sIHRhdSA9IHRhdSwgcHJpbnRfbWRsID0gcHJpbnRfbWRsKQogIG12X2Zjc3RfYXJ0MSA9IG1vZF9kaV93bChwY19kZlssMV0sIHBjX2RmWywtMV0sIG9yaWcgPSB0ZXN0X29yaWcsIG0gPSBvcHRfcHJlZF9hcnQxW1sxXV0sIHAgPSBvcHRfcHJlZF9hcnQxW1syXV0sIHRhdSA9IHRhdSwgYXJfdGYgPSAxLCBwcmludF9tZGwgPSBwcmludF9tZGwpCiAgbXZfZmNzdF9hcnQyID0gbW9kX2RpX3dsKHBjX2RmWywxXSwgcGNfZGZbLC0xXSwgb3JpZyA9IHRlc3Rfb3JpZywgbSA9IG9wdF9wcmVkX2FydDJbWzFdXSwgcCA9IG9wdF9wcmVkX2FydDJbWzJdXSwgdGF1ID0gdGF1LCBhcl90ZiA9IDIsIHByaW50X21kbCA9IHByaW50X21kbCkKICBtdl9mY3N0X2FydDMgPSBtb2RfZGlfd2wocGNfZGZbLDFdLCBwY19kZlssLTFdLCBvcmlnID0gdGVzdF9vcmlnLCBtID0gb3B0X3ByZWRfYXJ0M1tbMV1dLCBwID0gb3B0X3ByZWRfYXJ0M1tbMl1dLCB0YXUgPSB0YXUsIGFyX3RmID0gMywgcHJpbnRfbWRsID0gcHJpbnRfbWRsKQogICMgQ2FsY3VsYXRlIHRoZSBudW1iZXIgb2YgcHJlZGljdGlvbnMKICBpZiAoaXMubnVsbCh1dl9saXN0KSA9PSBUUlVFKXsKICAgICMgUHJpbnQgYSB3YXJuaW5nCiAgICBwcmludCgiV0FSTklORzogTm90IHN1cHBseWluZyBhbiBpbnB1dCBkYXRhIGZyYW1lIHdpbGwgcmVxdWlyZSB0aGlzIGZ1bmN0aW9uIHRvIHJ1biBmb3IgYSBzaWduaWZpY2FudCBhbW91bnQgb2YgdGltZSAoMWhyKykiKQogICAgIyBDYWxsIHRoZSBmdW5jdGlvbgogICAgIyBnZW5fdXZfdGVzdCA9IGZ1bmN0aW9uKGRmLCBuZmNzdCwgdGF1LCBub19ydW4gPSBjKDAsMCwwLDApKXsKICAgICMgcHJpbnQoaGVhZChwY19kZikpCiAgICB1dl9saXN0ID0gZ2VuX3V2X3Rlc3QoZGYgPSBwY19kZiwgbmZjc3QgPSBudGVzdCwgdGF1ID0gdGF1LCBub19ydW4gPSBub19ydW4pCiAgICAjIEFkZCB0byBhIGRhdGEgZnJhbWUKICAgICMgSW5jb3Jwb3JhdGUgdGhlIHJvbGxpbmcgcHJlZGljdGlvbnMgZnVuY3Rpb24gcmVzdWx0cyBoZXJlCiAgcGxvdF9tYXQgPSBjYmluZChwY19kZlsodGVzdF9vcmlnKzEpOm5yb3cocGNfZGYpLDFdLCBtdl9mY3N0JHloYXRbMTpudGVzdF0sIG12X2Zjc3RfYXJ0MSR5aGF0WzE6bnRlc3RdLCBtdl9mY3N0X2FydDIkeWhhdFsxOm50ZXN0XSwgbXZfZmNzdF9hcnQzJHloYXRbMTpudGVzdF0sIHV2X2xpc3RbWzFdXVsodGVzdF9vcmlnKzEpOnRlc3RfZW5kXSooLTEpLCB1dl9saXN0W1syXV1bKHRlc3Rfb3JpZysxKTp0ZXN0X2VuZF0qKC0xKSwgdXZfbGlzdFtbM11dWyh0ZXN0X29yaWcrMSk6dGVzdF9lbmRdKigtMSksIHV2X2xpc3RbWzRdXVsodGVzdF9vcmlnKzEpOnRlc3RfZW5kXSooLTEpKQogIH0gZWxzZSB7CiAgICAjIEFzc2lnbiB0aGUgY29sdW1ucyBvZiB0aGUgZGF0YSBmcmFtZQogICAgIyBoZWFkKHZhcl81cGNfMjAxMF91c2V0ZltbMV1dWyw2OjldKQogICAgIyBtb2RlbCB0eXBlICgxIC0gU0FWLCAyIC0gQVMsIDMgLSBHQVJDSCwgNCAtIEFEQVBUSVZFKSAKICAgICMgdGVzdF9kZiA9IGhlYWQodmFyXzVwY18yMDEwX3VzZXRmW1sxXV1bLDY6OV0pCiAgICAjIHRlc3RfZGYkU0FWCiAgICAjIHRlc3RfZGYkYEFicy4gU2xvcGVgCiAgICAjIHRlc3RfZGYkYEluZC4gR0FSQ0hgCiAgICAjIHRlc3RfZGYkQWRhcHRpdmUKICAgIHBsb3RfbWF0ID0gY2JpbmQocGNfZGZbKHRlc3Rfb3JpZysxKTpucm93KHBjX2RmKSwxXSwgbXZfZmNzdCR5aGF0WzE6bnRlc3RdLCBtdl9mY3N0X2FydDEkeWhhdFsxOm50ZXN0XSwgbXZfZmNzdF9hcnQyJHloYXRbMTpudGVzdF0sIG12X2Zjc3RfYXJ0MyR5aGF0WzE6bnRlc3RdLCB1dl9saXN0JFNBViwgdXZfbGlzdCRgQWJzLiBTbG9wZWAsIHV2X2xpc3QkYEluZC4gR0FSQ0hgLCB1dl9saXN0JEFkYXB0aXZlKQogIH0KICAjIENvdW50IHRoZSBOQXMgYW5kIHByaW50IGEgd2FybmluZwogIHByaW50KHBhc3RlKCJOT1RFOiBUaGVyZSBhcmUgIiwgc3VtKGlzLm5hKHBsb3RfbWF0KSksICIgTkEocykgaW4gdGhlIGRhdGFzZXQiLCBzZXAgPSAiIikpCiAgIyBMaW5lYXJseSBpbnRlcnBvbGF0ZSB0aGUgTkFzCiAgaWYgKG5hX2ludGVycCA9PSBUUlVFKXsKICAgICMgQXNzaWduIHRoZSBwbG90IG1hdHJpeCB0byBhIG5ldyB2YWx1ZQogICAgcGxvdF9tYXRfbmEgPC0gcGxvdF9tYXQKICAgICMgUHJpbnQgYSB3YXJuaW5nCiAgICBwcmludCgiV0FSTklORzogVGhlcmUgd2VyZSBtaXNzaW5nIHZhbHVlcyBpbiB0aGUgcGxvdCBtYXRyaXguIikKICAgICMgSW50ZXJwb2xhdGUgdGhlIE5BJ3MKICAgIGZvciAoaSBpbiAxOm5jb2wocGxvdF9tYXRfbmEpKXsKICAgICAgIyBJbnRlcnBvbGF0ZSB0aGUgZGF0YQogICAgICBwbG90X21hdFssaV0gPC0gbmEuYXBwcm94KHBsb3RfbWF0X25hWyxpXSkKICAgIH0KICB9CiAgIyBtb2RlbCB0eXBlICgxIC0gU0FWLCAyIC0gQVMsIDMgLSBHQVJDSCwgNCAtIEFEQVBUSVZFKQogICMgQWRkIGRlc2NyaXB0aXZlIHRpdGxlcyBvbnRvIHRoZSBwbG90X21hdAogIGNvbG5hbWVzKHBsb3RfbWF0KSA8LSBjKHJlc3BfdmFyLCAiTVYgQ0FWaWFSIiwgIk1WIENBVmlhUiArIEFSIiwgIk1WIENBVmlhUiArIFNBViIsICJNViBDQVZpYVIgKyBBUyIsICJTQVYiLCAiQWJzLiBTbG9wZSIsICJJbmQuIEdBUkNIIiwgIkFkYXB0aXZlIikKICAjIGNvbG5hbWVzKHBsb3RfbWF0KSA8LSBjKCJTUFkiLCAiTVYgQ0FWaWFSIiwgIk1WIENBVmlhUiArIEFSIiwgIk1WIENBVmlhUiArIFNBViIsICJNViBDQVZpYVIgKyBBUyIsICJTQVYiLCAiQWJzLiBTbG9wZSIsICJJbmQuIEdBUkNIIiwgIkFkYXB0aXZlIikKICAjIFBsb3QgZXZlcnl0aGluZwogIHBsb3QgPSBwbHRfZGF0YShwbG90X21hdCwgdGF1ID0gdGF1LCByZXNwX3ZhciA9IHJlc3BfdmFyLCBudGVzdCA9IG50ZXN0KQogICMgQ2FsY3VsYXRlIGxvc3NlcwogIGxfbGlzdCA9IGdlbl9sb3NzX3Rlc3QocGxvdF9tYXQsIHRhdSA9IHRhdSkKICAjIFB1dCBpbnRvIHRhYmxlcwogIHRhYmxlcyA9IHByZXR0eV90YWJsZXMocGxvdF9tYXQsIGxfbGlzdCwgdGF1ID0gdGF1LCBudGVzdCA9IG50ZXN0KQogICMgUnVuIHRoZSBmdW5jdGlvbiBmb3Igb3B0aW1hbCBwIGFuZCBtCiAgcG1fdGFibGUgPSBwcmV0dHlfcG0ob3B0X3ByZWRfbmxbWzNdXSwgb3B0X3ByZWRfYXJ0MVtbNF1dLCBvcHRfcHJlZF9hcnQyW1s0XV0sIG9wdF9wcmVkX2FydDNbWzRdXSkKICAjIEV4cG9ydCB0aGUgbWF0cml4CiAgaWYgKGV4cG9ydF9jc3YgPT0gMSl7CiAgICBleHBfZnVuYyh2YXJfZmlsZSA9IHBsb3RfbWF0LCBwYXRoLCBmaWxlbmFtZSkKICB9CiAgIyBQcmludCB0aGUgdGFibGVzIGFuZCB0aGUgcGxvdAogIHByaW50KHBsb3QpCiAgcHJpbnQodGFibGVzKQogIHByaW50KHBtX3RhYmxlKQogIHJldHVybihsaXN0KHBsb3RfbWF0LCBwbG90LCBsX2xpc3QsIHRhYmxlcywgcGxvdF9tYXRfbmEsIHBtX3RhYmxlKSkKfQpgYGAKCgoKYGBge3J9CiMnIEEgZnVuY3Rpb24gdG8gaW5wdXQgdGhlIFZhUiBmaWxlcywgcGxvdCB0aGVtIGFuZCBnZW5lcmF0ZSB0YWJsZXMKIycKIycgQHBhcmFtIGZpbGVfcGF0aCAtIGZpbGUgcGF0aCB0byB1c2UKIycgQHBhcmFtIGZpbGVuYW1lIC0gbmFtZSBvZiB0aGUgZmlsZQojJyBAcGFyYW0gdGF1IC0gcXVhbnRpbGUgdG8gdXNlCiMnIEBwYXJhbSByZXNwX3ZhciAtIHJlc3BvbnNlIHZhcmlhYmxlIHRvIHVzZSBpbiB0aGUgcGxvdAojJyBAcGFyYW0gbnRlc3QgLSBudW1iZXIgb2YgdGVzdCBwb2ludHMKIycgQHBhcmFtIGNuX2lucHV0IC0gY29sdW1uIG5hbWUgaW5wdXRzCiMnCiMnIEByZXR1cm4gLSBhIGxpc3Qgb2YgdGhlIHh0cyBmaWxlLCB0aGUgcGxvdCwgdGhlIGxvc3MgbGlzdCwgYW5kIHRhYmxlcwojJyBAZXhwb3J0IC0gYSBwbG90IGFuZCB0YWJsZXMKIycKIycgQGV4YW1wbGVzIC0gdGVzdCA9IHZhcl9pbnB1dF9kaXNwKCIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX1VTX0VURl9ydW5zLyIsInZhcl8xcGNfMjAwOF91c19ldGYuY3N2IiwgMC4wMSkKdmFyX2lucHV0X2Rpc3AgPSBmdW5jdGlvbihmaWxlX3BhdGgsIGZpbGVuYW1lLCB0YXUsIHJlc3BfdmFyID0gIlNQWSIsIG50ZXN0ID0gMjUwLCBjbl9pbnB1dCA9IGMoIlNQWSIsICJNViBDQVZpYVIiLCAiTVYgQ0FWaWFSICsgQVIiLCAiTVYgQ0FWaWFSICsgU0FWIiwgIk1WIENBVmlhUiArIEFTIiwgIlNBViIsICJBYnMuIFNsb3BlIiwgIkluZC4gR0FSQ0giLCAiQWRhcHRpdmUiKSl7CiMgdmFyX2lucHV0X2Rpc3AgPSBmdW5jdGlvbihmaWxlX3BhdGgsIGZpbGVuYW1lLCB0YXUsIHJlc3BfdmFyID0gIlNQWSIsIG50ZXN0ID0gMjUwLCBjbl9pbnB1dCA9IGMoIlNQWSIsICJNViBDQVZpYVIiLCAiTVYgQ0FWaWFSICsgQVIiLCAiTVYgQ0FWaWFSICsgU0FWIiwgIk1WIENBVmlhUiArIEFTIiwgIlNBViIsICJBYnMuIFNsb3BlIiwgIkluZC4gR0FSQ0giLCAiQWRhcHRpdmUiKSl7CiAgIyBJbXBvcnQgZGF0YQogIHBsb3RfbWF0ID0gcmVhZC5jc3YocGFzdGUwKGZpbGVfcGF0aCxmaWxlbmFtZSksIHNlcCA9ICIsIiwgaGVhZGVyID0gVCwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQogICMgRml4IGRhdGUgZm9ybWF0CiAgcGxvdF9tYXQkSW5kZXggPSBhcy5EYXRlKHBsb3RfbWF0JEluZGV4KQogICMgQ29udmVydCB0byBhbiB4dHMKICBwbG90X21hdCA9IHh0cyhwbG90X21hdFssLTFdLCBvcmRlci5ieSA9IHBsb3RfbWF0WywxXSkKICAjIEZpeCBjb2x1bW4gbmFtZXMKICBjb2xuYW1lcyhwbG90X21hdCkgPC0gY25faW5wdXQKICAjIFBsb3QgZXZlcnl0aGluZwogIHBsdF9kYXRhKHBsb3RfbWF0LCB0YXUgPSB0YXUsIHJlc3BfdmFyID0gcmVzcF92YXIsIG50ZXN0ID0gbnRlc3QpCiAgIyBwbG90ID0gcGx0X2RhdGEocGxvdF9tYXQsIHRhdSA9IHRhdSwgcmVzcF92YXIgPSByZXNwX3ZhciwgbnRlc3QgPSBudGVzdCkKICAjIENhbGN1bGF0ZSBsb3NzZXMKICBsX2xpc3QgPSBnZW5fbG9zc190ZXN0KHBsb3RfbWF0LCB0YXUgPSB0YXUpCiAgIyBQdXQgaW50byB0YWJsZXMKICBkZiA9IGFzLmRhdGEuZnJhbWUocmJpbmQobF9saXN0W1sxXV0sIGxfbGlzdFtbMl1dKSkKICAjIENhbGN1bGF0ZSBpbml0YWwgYW5kIGVuZGluZyB0aW1lIHZhbHVlCiAgc3RhcnQgPSBpbmRleChwbG90X21hdClbMV0KICBlbmQgPSBpbmRleChwbG90X21hdClbbnJvdyhwbG90X21hdCldCiAgIyBBZGQgcm93L2NvbHVtbiBuYW1lcwogIGNvbG5hbWVzKGRmKSA8LSBjb2xuYW1lcyhwbG90X21hdFssLTFdKQogIHJvd25hbWVzKGRmKSA8LSBjKCJMb3NzZXMiLCAiVmFSIEJyZWFrcyAoJSkiKQogICMgQ29udmVydCB0byBhIHRhYmxlCiAgcHJpbnQoZGYsIGRpZ2l0cyA9IDMpCiAgIyBwcmludChmb3JtYXR0YWJsZShkZiwgZGlnaXRzID0gMykpCiAgIyBkZiAlPiUga2FibGUoY2FwdGlvbiA9IHBhc3RlKCJDb21wYXJpc29uIG9mIFZhUiBNZXRob2RzIGZvciBhICIsIHRhdSoxMDAsICIlIFZhUiIsIHNlcCA9ICIiKSwgZGlnaXRzID0gMykgJT4lIGthYmxlX3N0eWxpbmcoInN0cmlwZWQiLCBmdWxsX3dpZHRoID0gRikgJT4lIGthYmxlX3N0eWxpbmcoKSAlPiUgZm9vdG5vdGUoZ2VuZXJhbCA9IHBhc3RlKCJDYWxjdWxhdGVkIHVzaW5nIiwgbnRlc3QsICJ0cmFkaW5nIGRheXMgZnJvbSIsIGFzLkRhdGUoc3RhcnQpLCAidG8iLCBhcy5EYXRlKGVuZCkpKQogICMgcG1fdGFibGUgPSBwcmV0dHlfdGFibGVzKHBsb3RfbWF0LCBsX2xpc3QsIHRhdSA9IHRhdSwgbnRlc3QgPSBudGVzdCkKICAjIFByaW50IHRoZSB0YWJsZXMgYW5kIHRoZSBwbG90CiAgIyBwcmludChwbG90KQogICMgcHJpbnQodGFibGVzKQogICMgcHJpbnQocG1fdGFibGUpCiAgIyBSZXR1cm4gdGhlIHh0cywgdGhlIHBsb3QsIHRoZSBsb3NzIGxpc3QsIGFuZCB0aGUgdGFibGVzCiAgcmV0dXJuKGxpc3QocGxvdF9tYXQpKQogICMgcmV0dXJuKGxpc3QocGxvdF9tYXQsIHBsb3QsIGxfbGlzdCwgdGFibGVzKSkKfQpgYGAKCgojIyAyMDA4IEVuZGluZwoKIyMjIFUuUy4gRVRGcwoKYGBge3J9CiMgcmV0dXJuKGxpc3QocGxvdF9tYXQsIHBsb3QsIGxfbGlzdCwgdGFibGVzKSkKCiMgQ2FsbCB0aGUgYWJvdmUgZnVuY3Rpb24KdjFfMjAwOF91c2V0ZiA9IHZhcl9pbnB1dF9kaXNwKCIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX1VTX0VURl9ydW5zLyIsInZhcl8xcGNfMjAwOF91c19ldGYuY3N2IiwgMC4wMSkKIyBwcmV0dHlfdGFibGVzKHYxXzIwMDhfdXNldGZbWzFdXSwgdjFfMjAwOF91c2V0ZltbM11dLCB0YXUgPSAwLjAxLCBudGVzdCA9IDI1MCkKdjVfMjAwOF91c2V0ZiA9IHZhcl9pbnB1dF9kaXNwKCIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX1VTX0VURl9ydW5zLyIsInZhcl81cGNfMjAwOF91c19ldGYuY3N2IiwgMC4wNSkKdjEwXzIwMDhfdXNldGYgPSB2YXJfaW5wdXRfZGlzcCgiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9VU19FVEZfcnVucy8iLCJ2YXJfMTBwY18yMDA4X3VzX2V0Zi5jc3YiLCAwLjEwKQoKIyBoZWFkKHYxMF8yMDA4X3VzZXRmW1sxXV0pCiMgdjEwXzIwMDhfdXNldGYKYGBgCgpUaGUgcmVzdWx0cyBmb3IgdGhlIFUuUy4gRVRGcyBjbGVhcmx5IHNob3cgdGhhdCB0aGUgdW5pdmFyaWF0ZSBtb2RlbCBvdXRwZXJmb3JtcyB0aGUgbXVsdGl2YXJpYXRlIG1vZGVsIGR1cmluZyB0aGUgZ3JlYXQgcmVjZXNzaW9uLgoKYGBge3J9CiMgMSUsIDUlLCAxMCUgVmFSIC0gMjAwOCAtIDFzdCBzZXQgb2YgcHJlZGljdG9ycwojIHZhcl8xcGNfMjAwOF91c19ldGYgPSBjYXZfc2ltdWwoYygiWExVIiwgIlhMUCIsICJYTFYiLCAiWExLIiwgIlhMWSIsICJYTEkiLCAiWExGIiwgIlhMQiIsICJYTEUiKSwgcmVzcF92YXIgPSAiU1BZIiwgc3RhcnRfZGF0ZSA9ICIyMDA0LTAxLTAxIiwgZW5kX2RhdGUgPSAiMjAwOC0xMi0zMSIsIG52YWwgPSAyNTAsIG50ZXN0ID0gMjUwLCBsb3dfbSA9IDEsIGhpZ2hfbSA9IDksIGxvd19wID0gMSwgaGlnaF9wID0gMTAsIHRhdSA9IDAuMDEsIHByaW50X21kbCA9IDEsIHByaW50X21wID0gMSwgcGF0aCA9ICIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX1VTX0VURl9ydW5zLyIsIGZpbGVuYW1lID0gInZhcl8xcGNfMjAwOF91c19ldGYuY3N2IiwgdXZfbGlzdCA9IHZhcl8xcGNfMjAwOF91c2V0ZltbMV1dKQoKIyB2YXJfNXBjXzIwMDhfdXNfZXRmID0gY2F2X3NpbXVsKGMoIlhMVSIsICJYTFAiLCAiWExWIiwgIlhMSyIsICJYTFkiLCAiWExJIiwgIlhMRiIsICJYTEIiLCAiWExFIiksIHJlc3BfdmFyID0gIlNQWSIsIHN0YXJ0X2RhdGUgPSAiMjAwNC0wMS0wMSIsIGVuZF9kYXRlID0gIjIwMDgtMTItMzEiLCBudmFsID0gMjUwLCBudGVzdCA9IDI1MCwgbG93X20gPSAxLCBoaWdoX20gPSA5LCBsb3dfcCA9IDEsIGhpZ2hfcCA9IDEwLHRhdSA9IDAuMDUsIHByaW50X21kbCA9IDEsIHByaW50X21wID0gMSwgcGF0aCA9ICIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX1VTX0VURl9ydW5zLyIsIGZpbGVuYW1lID0gInZhcl81cGNfMjAwOF91c19ldGYuY3N2IiwgdXZfbGlzdCA9IHZhcl81cGNfMjAwOF91c2V0ZltbMV1dKQoKIyB2YXJfMTBwY18yMDA4X3VzX2V0ZiA9IGNhdl9zaW11bChjKCJYTFUiLCAiWExQIiwgIlhMViIsICJYTEsiLCAiWExZIiwgIlhMSSIsICJYTEYiLCAiWExCIiwgIlhMRSIpLCByZXNwX3ZhciA9ICJTUFkiLCBzdGFydF9kYXRlID0gIjIwMDQtMDEtMDEiLCBlbmRfZGF0ZSA9ICIyMDA4LTEyLTMxIiwgbnZhbCA9IDI1MCwgbnRlc3QgPSAyNTAsIGxvd19tID0gMSwgaGlnaF9tID0gOSwgbG93X3AgPSAxLCBoaWdoX3AgPSAxMCx0YXUgPSAwLjEwLCBwcmludF9tZGwgPSAxLCBwcmludF9tcCA9IDEsIHBhdGggPSAiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9VU19FVEZfcnVucy8iLCBmaWxlbmFtZSA9ICJ2YXJfMTBwY18yMDA4X3VzX2V0Zi5jc3YiLCB1dl9saXN0ID0gdmFyXzEwcGNfMjAwOF91c2V0ZltbMV1dKQpgYGAKCiMjIyBHbG9iYWwgRVRGcwoKYGBge3J9CiMgQ2FsbCB0aGUgYWJvdmUgZnVuY3Rpb24KdjFfMjAwOF9nbG9iZXRmID0gdmFyX2lucHV0X2Rpc3AoIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfZ2xvYl9FVEZfcnVucy8iLCJ2YXJfMXBjXzIwMDhfZ2xvYl9ldGYuY3N2IiwgMC4wMSkKdjVfMjAwOF9nbG9iZXRmID0gdmFyX2lucHV0X2Rpc3AoIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfZ2xvYl9FVEZfcnVucy8iLCJ2YXJfNXBjXzIwMDhfZ2xvYl9ldGYuY3N2IiwgMC4wNSkKdjEwXzIwMDhfZ2xvYmV0ZiA9IHZhcl9pbnB1dF9kaXNwKCIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2dsb2JfRVRGX3J1bnMvIiwidmFyXzEwcGNfMjAwOF9nbG9iX2V0Zi5jc3YiLCAwLjEwKQpgYGAKCldoaWxlIHRoZSBtb2RlbCB3aXRoIHRoZSBnbG9iYWwgRVRGcyBhcyBwcmVkaWN0b3JzIHBlcmZvcm1zIGJldHRlciB0aGFuIHRoZSBtb2RlbCB3aXRoIFUuUy4gRVRGcywgdGhlIHVuaXZhcmlhdGUgQ0FWaWFSIG1vZGVsIG91dHBlcmZvcm1zIHRoZSBtdWx0aXZhcmlhdGUgbW9kZWwuCgpgYGB7cn0KIyAxJSwgNSUsIDEwJSBWYVIgLSAyMDA4IC0gMm5kIHNldCBvZiBwcmVkaWN0b3JzCiMgdmFyXzFwY18yMDA4X2dsb2JfZXRmID0gY2F2X3NpbXVsKGMoIkpYSSIsICJLWEkiLCAiSVhKIiwgIklYUCIsICJJWE4iLCAiUlhJIiwgIkVYSSIsICJJWEciLCAiTVhJIiwgIklYQyIpLCByZXNwX3ZhciA9ICJTUFkiLCBzdGFydF9kYXRlID0gIjIwMDQtMDEtMDEiLCBlbmRfZGF0ZSA9ICIyMDA4LTEyLTMxIiwgbnZhbCA9IDI1MCwgbnRlc3QgPSAyNTAsIGxvd19tID0gMSwgaGlnaF9tID0gMTAsIGxvd19wID0gMSwgaGlnaF9wID0gMTAsIHRhdSA9IDAuMDEsIHByaW50X21kbCA9IDEsIHByaW50X21wID0gMSwgcGF0aCA9ICIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2dsb2JfRVRGX3J1bnMvIiwgZmlsZW5hbWUgPSAidmFyXzFwY18yMDA4X2dsb2JfZXRmLmNzdiIsIHV2X2xpc3QgPSB2YXJfMXBjXzIwMDhfdXNldGZbWzFdXSkKCiMgdmFyXzVwY18yMDA4X2dsb2JfZXRmID0gY2F2X3NpbXVsKGMoIkpYSSIsICJLWEkiLCAiSVhKIiwgIklYUCIsICJJWE4iLCAiUlhJIiwgIkVYSSIsICJJWEciLCAiTVhJIiwgIklYQyIpLCByZXNwX3ZhciA9ICJTUFkiLCBzdGFydF9kYXRlID0gIjIwMDQtMDEtMDEiLCBlbmRfZGF0ZSA9ICIyMDA4LTEyLTMxIiwgbnZhbCA9IDI1MCwgbnRlc3QgPSAyNTAsIGxvd19tID0gMSwgaGlnaF9tID0gMTAsIGxvd19wID0gMSwgaGlnaF9wID0gMTAsdGF1ID0gMC4wNSwgcHJpbnRfbWRsID0gMSwgcHJpbnRfbXAgPSAxLCBwYXRoID0gIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfZ2xvYl9FVEZfcnVucy8iLCBmaWxlbmFtZSA9ICJ2YXJfNXBjXzIwMDhfZ2xvYl9ldGYuY3N2IiwgdXZfbGlzdCA9IHZhcl81cGNfMjAwOF91c2V0ZltbMV1dKQoKIyB2YXJfMTBwY18yMDA4X2dsb2JfZXRmID0gY2F2X3NpbXVsKGMoIkpYSSIsICJLWEkiLCAiSVhKIiwgIklYUCIsICJJWE4iLCAiUlhJIiwgIkVYSSIsICJJWEciLCAiTVhJIiwgIklYQyIpLCByZXNwX3ZhciA9ICJTUFkiLCBzdGFydF9kYXRlID0gIjIwMDQtMDEtMDEiLCBlbmRfZGF0ZSA9ICIyMDA4LTEyLTMxIiwgbnZhbCA9IDI1MCwgbnRlc3QgPSAyNTAsIGxvd19tID0gMSwgaGlnaF9tID0gMTAsIGxvd19wID0gMSwgaGlnaF9wID0gMTAsdGF1ID0gMC4xMCwgcHJpbnRfbWRsID0gMSwgcHJpbnRfbXAgPSAxLCBwYXRoID0gIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfZ2xvYl9FVEZfcnVucy8iLCBmaWxlbmFtZSA9ICJ2YXJfMTBwY18yMDA4X2dsb2JfZXRmLmNzdiIsIHV2X2xpc3QgPSB2YXJfMTBwY18yMDA4X3VzZXRmW1sxXV0pCmBgYAoKIyMjIENvbW1vZGl0eSBFVEZzCgpgYGB7cn0KIyAxJSwgNSUsIDEwJSBWYVIgLSAyMDA4IC0gM3JkIHNldCBvZiBwcmVkaWN0b3JzCiMgdmFyXzFwY18yMDA4X2NvbW1fZXRmID0gY2F2X3NpbXVsKGMoIkRCQSIsICJEQkMiLCAiREJFIiwgIkRCQiIpLCByZXNwX3ZhciA9ICJTUFkiLCBzdGFydF9kYXRlID0gIjIwMDQtMDEtMDEiLCBlbmRfZGF0ZSA9ICIyMDA4LTEyLTMxIiwgbnZhbCA9IDI1MCwgbnRlc3QgPSAyNTAsIGxvd19tID0gMSwgaGlnaF9tID0gNCwgbG93X3AgPSAxLCBoaWdoX3AgPSAxMCwgdGF1ID0gMC4wMSwgcHJpbnRfbWRsID0gMSwgcHJpbnRfbXAgPSAxLCBwYXRoID0gIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfY29tbV9FVEZfcnVucy8iLCBmaWxlbmFtZSA9ICJ2YXJfMXBjXzIwMDhfY29tbV9ldGYuY3N2IiwgdXZfbGlzdCA9IHZhcl8xcGNfMjAwOF91c2V0ZltbMV1dKQoKIyB2YXJfNXBjXzIwMDhfY29tbV9ldGYgPSBjYXZfc2ltdWwoYygiREJBIiwgIkRCQyIsICJEQkUiLCAiREJCIiksIHJlc3BfdmFyID0gIlNQWSIsIHN0YXJ0X2RhdGUgPSAiMjAwNC0wMS0wMSIsIGVuZF9kYXRlID0gIjIwMDgtMTItMzEiLCBudmFsID0gMjUwLCBudGVzdCA9IDI1MCwgbG93X20gPSAxLCBoaWdoX20gPSA0LCBsb3dfcCA9IDEsIGhpZ2hfcCA9IDEwLHRhdSA9IDAuMDUsIHByaW50X21kbCA9IDEsIHByaW50X21wID0gMSwgcGF0aCA9ICIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2NvbW1fRVRGX3J1bnMvIiwgZmlsZW5hbWUgPSAidmFyXzVwY18yMDA4X2NvbW1fZXRmLmNzdiIsIHV2X2xpc3QgPSB2YXJfNXBjXzIwMDhfdXNldGZbWzFdXSkKCiMgdmFyXzEwcGNfMjAwOF9jb21tX2V0ZiA9IGNhdl9zaW11bChjKCJEQkEiLCAiREJDIiwgIkRCRSIsICJEQkIiKSwgcmVzcF92YXIgPSAiU1BZIiwgc3RhcnRfZGF0ZSA9ICIyMDA0LTAxLTAxIiwgZW5kX2RhdGUgPSAiMjAwOC0xMi0zMSIsIG52YWwgPSAyNTAsIG50ZXN0ID0gMjUwLCBsb3dfbSA9IDEsIGhpZ2hfbSA9IDQsIGxvd19wID0gMSwgaGlnaF9wID0gMTAsdGF1ID0gMC4xMCwgcHJpbnRfbWRsID0gMSwgcHJpbnRfbXAgPSAxLCBwYXRoID0gIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfY29tbV9FVEZfcnVucy8iLCBmaWxlbmFtZSA9ICJ2YXJfMTBwY18yMDA4X2NvbW1fZXRmLmNzdiIsIHV2X2xpc3QgPSB2YXJfMTBwY18yMDA4X3VzZXRmW1sxXV0pCmBgYAoKCgojIyMgQm9uZCBFVEZzCgpgYGB7cn0KIyBDYWxsIHRoZSBhYm92ZSBmdW5jdGlvbgp2MV8yMDA4X2JvbmRldGYgPSB2YXJfaW5wdXRfZGlzcCgiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9ib25kX0VURl9ydW5zLyIsInZhcl8xcGNfMjAwOF9ib25kX2V0Zi5jc3YiLCAwLjAxKQp2NV8yMDA4X2JvbmRldGYgPSB2YXJfaW5wdXRfZGlzcCgiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9ib25kX0VURl9ydW5zLyIsInZhcl81cGNfMjAwOF9ib25kX2V0Zi5jc3YiLCAwLjA1KQp2MTBfMjAwOF9ib25kZXRmID0gdmFyX2lucHV0X2Rpc3AoIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfYm9uZF9FVEZfcnVucy8iLCJ2YXJfMTBwY18yMDA4X2JvbmRfZXRmLmNzdiIsIDAuMTApCmBgYAoKQXMgd2l0aCB0aGUgcHJldmlvdXMgdHdvIHJ1bnMsIHRoZSB1bml2YXJpYXRlIG1vZGVsIG91dHBlcmZvcm1zIHRoZSBtdWx0aXZhcmlhdGUgbW9kZWwuCgpgYGB7cn0KIyBpU2hhcmVzIDEtMyBZZWFyIFRyZWFzdXJ5IEJvbmQgRnVuZCAoU0hZKQojIGlTaGFyZXMgNy0xMCBZZWFyIFRyZWFzdXJ5IEJvbmQgRnVuZCAoSUVGKQojIGlTaGFyZXMgMjArIFllYXIgVHJlYXN1cnkgQm9uZCBGdW5kIChUTFQpCiMgaVNoYXJlcyBpQm94eCAkIEludmVzdG1lbnQgR3JhZGUgQ29ycG9yYXRlIEJvbmQgRVRGIChMUUQpCgojIDElLCA1JSwgMTAlIFZhUiAtIDIwMDggLSA0dGggc2V0IG9mIHByZWRpY3RvcnMKIyB2YXJfMXBjXzIwMDhfYm9uZF9ldGYgPSBjYXZfc2ltdWwoYygiU0hZIiwgIklFRiIsICJUTFQiLCAiTFFEIiksIHJlc3BfdmFyID0gIlNQWSIsIHN0YXJ0X2RhdGUgPSAiMjAwNC0wMS0wMSIsIGVuZF9kYXRlID0gIjIwMDgtMTItMzEiLCBudmFsID0gMjUwLCBudGVzdCA9IDI1MCwgbG93X20gPSAxLCBoaWdoX20gPSA0LCBsb3dfcCA9IDEsIGhpZ2hfcCA9IDEwLCB0YXUgPSAwLjAxLCBwcmludF9tZGwgPSAxLCBwcmludF9tcCA9IDEsIHBhdGggPSAiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9ib25kX0VURl9ydW5zLyIsIGZpbGVuYW1lID0gInZhcl8xcGNfMjAwOF9ib25kX2V0Zi5jc3YiLCB1dl9saXN0ID0gdmFyXzFwY18yMDA4X3VzZXRmW1sxXV0pCgojIHZhcl81cGNfMjAwOF9ib25kX2V0ZiA9IGNhdl9zaW11bChjKCJTSFkiLCAiSUVGIiwgIlRMVCIsICJMUUQiKSwgcmVzcF92YXIgPSAiU1BZIiwgc3RhcnRfZGF0ZSA9ICIyMDA0LTAxLTAxIiwgZW5kX2RhdGUgPSAiMjAwOC0xMi0zMSIsIG52YWwgPSAyNTAsIG50ZXN0ID0gMjUwLCBsb3dfbSA9IDEsIGhpZ2hfbSA9IDQsIGxvd19wID0gMSwgaGlnaF9wID0gMTAsdGF1ID0gMC4wNSwgcHJpbnRfbWRsID0gMSwgcHJpbnRfbXAgPSAxLCBwYXRoID0gIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfYm9uZF9FVEZfcnVucy8iLCBmaWxlbmFtZSA9ICJ2YXJfNXBjXzIwMDhfYm9uZF9ldGYuY3N2IiwgdXZfbGlzdCA9IHZhcl81cGNfMjAwOF91c2V0ZltbMV1dKQoKIyB2YXJfMTBwY18yMDA4X2JvbmRfZXRmID0gY2F2X3NpbXVsKGMoIlNIWSIsICJJRUYiLCAiVExUIiwgIkxRRCIpLCByZXNwX3ZhciA9ICJTUFkiLCBzdGFydF9kYXRlID0gIjIwMDQtMDEtMDEiLCBlbmRfZGF0ZSA9ICIyMDA4LTEyLTMxIiwgbnZhbCA9IDI1MCwgbnRlc3QgPSAyNTAsIGxvd19tID0gMSwgaGlnaF9tID0gNCwgbG93X3AgPSAxLCBoaWdoX3AgPSAxMCx0YXUgPSAwLjEwLCBwcmludF9tZGwgPSAxLCBwcmludF9tcCA9IDEsIHBhdGggPSAiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9ib25kX0VURl9ydW5zLyIsIGZpbGVuYW1lID0gInZhcl8xMHBjXzIwMDhfYm9uZF9ldGYuY3N2IiwgdXZfbGlzdCA9IHZhcl8xMHBjXzIwMDhfdXNldGZbWzFdXSkKYGBgCgojIyMgQWxsIEVURnMKCmBgYHtyfQojIENhbGwgdGhlIGFib3ZlIGZ1bmN0aW9uCnYxXzIwMDhfYWxsZXRmID0gdmFyX2lucHV0X2Rpc3AoIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfYWxsX0VURl9ydW5zLyIsInZhcl8xcGNfMjAwOF9hbGxfZXRmLmNzdiIsIDAuMDEpCnY1XzIwMDhfYWxsZXRmID0gdmFyX2lucHV0X2Rpc3AoIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfYWxsX0VURl9ydW5zLyIsInZhcl81cGNfMjAwOF9hbGxfZXRmLmNzdiIsIDAuMDUpCnYxMF8yMDA4X2FsbGV0ZiA9IHZhcl9pbnB1dF9kaXNwKCIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2FsbF9FVEZfcnVucy8iLCJ2YXJfMTBwY18yMDA4X2FsbF9ldGYuY3N2IiwgMC4xMCkKYGBgCgpXaGlsZSB0aGUgaW5jbHVzaW9uIG9mIG1vcmUgZXhwbGFuYXRvcnkgdmFyaWFibGVzIHNlZW1zIHRvIGhlbHAgdGhlIGZvcmVjYXN0LCB0aGUgdW5pdmFyaWF0ZSBtb2RlbCBvdXRwZXJmb3JtcyB0aGUgbXVsdGl2YXJpYXRlIG1vZGVsLgoKYGBge3J9CiMgMSUsIDUlLCAxMCUgVmFSIC0gMjAwOCAtIDV0aCBzZXQgb2YgcHJlZGljdG9ycwojIHZhcl8xcGNfMjAwOF9hbGxfZXRmID0gY2F2X3NpbXVsKGMoIlhMVSIsICJYTFAiLCAiWExWIiwgIlhMSyIsICJYTFkiLCAiWExJIiwgIlhMRiIsICJYTEIiLCAiWExFIiwgIkpYSSIsICJLWEkiLCAiSVhKIiwgIklYUCIsICJJWE4iLCAiUlhJIiwgIkVYSSIsICJJWEciLCAiTVhJIiwgIklYQyIsICJTSFkiLCAiSUVGIiwgIlRMVCIsICJMUUQiKSwgcmVzcF92YXIgPSAiU1BZIiwgc3RhcnRfZGF0ZSA9ICIyMDA0LTAxLTAxIiwgZW5kX2RhdGUgPSAiMjAwOC0xMi0zMSIsIG52YWwgPSAyNTAsIG50ZXN0ID0gMjUwLCBsb3dfbSA9IDEsIGhpZ2hfbSA9IDIzLCBsb3dfcCA9IDEsIGhpZ2hfcCA9IDEwLCB0YXUgPSAwLjAxLCBwcmludF9tZGwgPSAxLCBwcmludF9tcCA9IDEsIHBhdGggPSAiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9hbGxfRVRGX3J1bnMvIiwgZmlsZW5hbWUgPSAidmFyXzFwY18yMDA4X2FsbF9ldGYuY3N2IiwgdXZfbGlzdCA9IHZhcl8xcGNfMjAwOF91c2V0ZltbMV1dKQoKIyB2YXJfNXBjXzIwMDhfYWxsX2V0ZiA9IGNhdl9zaW11bChjKCJYTFUiLCAiWExQIiwgIlhMViIsICJYTEsiLCAiWExZIiwgIlhMSSIsICJYTEYiLCAiWExCIiwgIlhMRSIsICJKWEkiLCAiS1hJIiwgIklYSiIsICJJWFAiLCAiSVhOIiwgIlJYSSIsICJFWEkiLCAiSVhHIiwgIk1YSSIsICJJWEMiLCAiU0hZIiwgIklFRiIsICJUTFQiLCAiTFFEIiksIHJlc3BfdmFyID0gIlNQWSIsIHN0YXJ0X2RhdGUgPSAiMjAwNC0wMS0wMSIsIGVuZF9kYXRlID0gIjIwMDgtMTItMzEiLCBudmFsID0gMjUwLCBudGVzdCA9IDI1MCwgbG93X20gPSAxLCBoaWdoX20gPSAyMywgbG93X3AgPSAxLCBoaWdoX3AgPSAxMCx0YXUgPSAwLjA1LCBwcmludF9tZGwgPSAxLCBwcmludF9tcCA9IDEsIHBhdGggPSAiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9hbGxfRVRGX3J1bnMvIiwgZmlsZW5hbWUgPSAidmFyXzVwY18yMDA4X2FsbF9ldGYuY3N2IiwgdXZfbGlzdCA9IHZhcl81cGNfMjAwOF91c2V0ZltbMV1dKQoKIyB2YXJfMTBwY18yMDA4X2FsbF9ldGYgPSBjYXZfc2ltdWwoYygiWExVIiwgIlhMUCIsICJYTFYiLCAiWExLIiwgIlhMWSIsICJYTEkiLCAiWExGIiwgIlhMQiIsICJYTEUiLCAiSlhJIiwgIktYSSIsICJJWEoiLCAiSVhQIiwgIklYTiIsICJSWEkiLCAiRVhJIiwgIklYRyIsICJNWEkiLCAiSVhDIiwgIlNIWSIsICJJRUYiLCAiVExUIiwgIkxRRCIpLCByZXNwX3ZhciA9ICJTUFkiLCBzdGFydF9kYXRlID0gIjIwMDQtMDEtMDEiLCBlbmRfZGF0ZSA9ICIyMDA4LTEyLTMxIiwgbnZhbCA9IDI1MCwgbnRlc3QgPSAyNTAsIGxvd19tID0gMSwgaGlnaF9tID0gMjMsIGxvd19wID0gMSwgaGlnaF9wID0gMTAsdGF1ID0gMC4xMCwgcHJpbnRfbWRsID0gMSwgcHJpbnRfbXAgPSAxLCBwYXRoID0gIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfYWxsX0VURl9ydW5zLyIsIGZpbGVuYW1lID0gInZhcl8xMHBjXzIwMDhfYWxsX2V0Zi5jc3YiLCB1dl9saXN0ID0gdmFyXzEwcGNfMjAwOF91c2V0ZltbMV1dKQpgYGAKCiMjIDIwMTAgRW5kaW5nCgojIyMgVS5TLiBFVEZzCgpgYGB7cn0KIyBDYWxsIHRoZSBhYm92ZSBmdW5jdGlvbgp2MV8yMDEwX3VzZXRmID0gdmFyX2lucHV0X2Rpc3AoIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfVVNfRVRGX3J1bnMvIiwidmFyXzFwY18yMDEwX3VzX2V0Zi5jc3YiLCAwLjAxKQp2NV8yMDEwX3VzZXRmID0gdmFyX2lucHV0X2Rpc3AoIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfVVNfRVRGX3J1bnMvIiwidmFyXzVwY18yMDEwX3VzX2V0Zi5jc3YiLCAwLjA1KQp2MTBfMjAxMF91c2V0ZiA9IHZhcl9pbnB1dF9kaXNwKCIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX1VTX0VURl9ydW5zLyIsInZhcl8xMHBjXzIwMTBfdXNfZXRmLmNzdiIsIDAuMTApCmBgYAoKVGhlIHJlc3VsdHMgYXJlIG11Y2ggYmV0dGVyIGZvciB0aGUgbXVsdGl2YXJpYXRlIG1vZGVsIGhlcmUgZHVyaW5nIGEgbW9yZSBiZW5pZ24gcGVyaW9kLgoKYGBge3J9CiMgMSUsIDUlLCAxMCUgVmFSIC0gMjAxMCAtIDFzdCBzZXQgb2YgcHJlZGljdG9ycwojIHZhcl8xcGNfMjAxMF91c19ldGYgPSBjYXZfc2ltdWwoYygiWExVIiwgIlhMUCIsICJYTFYiLCAiWExLIiwgIlhMWSIsICJYTEkiLCAiWExGIiwgIlhMQiIsICJYTEUiKSwgcmVzcF92YXIgPSAiU1BZIiwgc3RhcnRfZGF0ZSA9ICIyMDA2LTAxLTAxIiwgZW5kX2RhdGUgPSAiMjAxMC0xMi0zMSIsIG52YWwgPSAyNTAsIG50ZXN0ID0gMjUwLCBsb3dfbSA9IDEsIGhpZ2hfbSA9IDksIGxvd19wID0gMSwgaGlnaF9wID0gMTAsIHRhdSA9IDAuMDEsIHByaW50X21kbCA9IDEsIHByaW50X21wID0gMSwgcGF0aCA9ICIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX1VTX0VURl9ydW5zLyIsIGZpbGVuYW1lID0gInZhcl8xcGNfMjAxMF91c19ldGYuY3N2IiwgdXZfbGlzdCA9IHZhcl8xcGNfMjAxMF91c2V0ZltbMV1dKQoKIyB2YXJfNXBjXzIwMTBfdXNfZXRmID0gY2F2X3NpbXVsKGMoIlhMVSIsICJYTFAiLCAiWExWIiwgIlhMSyIsICJYTFkiLCAiWExJIiwgIlhMRiIsICJYTEIiLCAiWExFIiksIHJlc3BfdmFyID0gIlNQWSIsIHN0YXJ0X2RhdGUgPSAiMjAwNi0wMS0wMSIsIGVuZF9kYXRlID0gIjIwMTAtMTItMzEiLCBudmFsID0gMjUwLCBudGVzdCA9IDI1MCwgbG93X20gPSAxLCBoaWdoX20gPSA5LCBsb3dfcCA9IDEsIGhpZ2hfcCA9IDEwLHRhdSA9IDAuMDUsIHByaW50X21kbCA9IDEsIHByaW50X21wID0gMSwgcGF0aCA9ICIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX1VTX0VURl9ydW5zLyIsIGZpbGVuYW1lID0gInZhcl81cGNfMjAxMF91c19ldGYuY3N2IiwgdXZfbGlzdCA9IHZhcl81cGNfMjAxMF91c2V0ZltbMV1dKQoKIyB2YXJfMTBwY18yMDEwX3VzX2V0ZiA9IGNhdl9zaW11bChjKCJYTFUiLCAiWExQIiwgIlhMViIsICJYTEsiLCAiWExZIiwgIlhMSSIsICJYTEYiLCAiWExCIiwgIlhMRSIpLCByZXNwX3ZhciA9ICJTUFkiLCBzdGFydF9kYXRlID0gIjIwMDYtMDEtMDEiLCBlbmRfZGF0ZSA9ICIyMDEwLTEyLTMxIiwgbnZhbCA9IDI1MCwgbnRlc3QgPSAyNTAsIGxvd19tID0gMSwgaGlnaF9tID0gOSwgbG93X3AgPSAxLCBoaWdoX3AgPSAxMCx0YXUgPSAwLjEwLCBwcmludF9tZGwgPSAxLCBwcmludF9tcCA9IDEsIHBhdGggPSAiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9VU19FVEZfcnVucy8iLCBmaWxlbmFtZSA9ICJ2YXJfMTBwY18yMDEwX3VzX2V0Zi5jc3YiLCB1dl9saXN0ID0gdmFyXzEwcGNfMjAxMF91c2V0ZltbMV1dKQpgYGAKCiMjIyBHbG9iYWwgRVRGcwoKYGBge3J9CiMgQ2FsbCB0aGUgYWJvdmUgZnVuY3Rpb24KdjFfMjAxMF9nbG9iZXRmID0gdmFyX2lucHV0X2Rpc3AoIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfZ2xvYl9FVEZfcnVucy8iLCJ2YXJfMXBjXzIwMTBfZ2xvYl9ldGYuY3N2IiwgMC4wMSkKdjVfMjAxMF9nbG9iZXRmID0gdmFyX2lucHV0X2Rpc3AoIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfZ2xvYl9FVEZfcnVucy8iLCJ2YXJfNXBjXzIwMTBfZ2xvYl9ldGYuY3N2IiwgMC4wNSkKdjEwXzIwMTBfZ2xvYmV0ZiA9IHZhcl9pbnB1dF9kaXNwKCIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2dsb2JfRVRGX3J1bnMvIiwidmFyXzEwcGNfMjAxMF9nbG9iX2V0Zi5jc3YiLCAwLjEwKQpgYGAKCkFzIHdpdGggdGhlIFUuUy4gRVRGcywgdGhlIHJlc3VsdHMgYXJlIGJldHRlci4KCmBgYHtyfQojIDElLCA1JSwgMTAlIFZhUiAtIDIwMTAgLSAybmQgc2V0IG9mIHByZWRpY3RvcnMKIyB2YXJfMXBjXzIwMTBfZ2xvYl9ldGYgPSBjYXZfc2ltdWwoYygiSlhJIiwgIktYSSIsICJJWEoiLCAiSVhQIiwgIklYTiIsICJSWEkiLCAiRVhJIiwgIklYRyIsICJNWEkiLCAiSVhDIiksIHJlc3BfdmFyID0gIlNQWSIsIHN0YXJ0X2RhdGUgPSAiMjAwNi0wMS0wMSIsIGVuZF9kYXRlID0gIjIwMTAtMTItMzEiLCBudmFsID0gMjUwLCBudGVzdCA9IDI1MCwgbG93X20gPSAxLCBoaWdoX20gPSAxMCwgbG93X3AgPSAxLCBoaWdoX3AgPSAxMCwgdGF1ID0gMC4wMSwgcHJpbnRfbWRsID0gMSwgcHJpbnRfbXAgPSAxLCBwYXRoID0gIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfZ2xvYl9FVEZfcnVucy8iLCBmaWxlbmFtZSA9ICJ2YXJfMXBjXzIwMTBfZ2xvYl9ldGYuY3N2IiwgdXZfbGlzdCA9IHZhcl8xcGNfMjAxMF91c2V0ZltbMV1dKQoKIyB2YXJfNXBjXzIwMTBfZ2xvYl9ldGYgPSBjYXZfc2ltdWwoYygiSlhJIiwgIktYSSIsICJJWEoiLCAiSVhQIiwgIklYTiIsICJSWEkiLCAiRVhJIiwgIklYRyIsICJNWEkiLCAiSVhDIiksIHJlc3BfdmFyID0gIlNQWSIsIHN0YXJ0X2RhdGUgPSAiMjAwNi0wMS0wMSIsIGVuZF9kYXRlID0gIjIwMTAtMTItMzEiLCBudmFsID0gMjUwLCBudGVzdCA9IDI1MCwgbG93X20gPSAxLCBoaWdoX20gPSAxMCwgbG93X3AgPSAxLCBoaWdoX3AgPSAxMCx0YXUgPSAwLjA1LCBwcmludF9tZGwgPSAxLCBwcmludF9tcCA9IDEsIHBhdGggPSAiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9nbG9iX0VURl9ydW5zLyIsIGZpbGVuYW1lID0gInZhcl81cGNfMjAxMF9nbG9iX2V0Zi5jc3YiLCB1dl9saXN0ID0gdmFyXzVwY18yMDEwX3VzZXRmW1sxXV0pCgojIHZhcl8xMHBjXzIwMTBfZ2xvYl9ldGYgPSBjYXZfc2ltdWwoYygiSlhJIiwgIktYSSIsICJJWEoiLCAiSVhQIiwgIklYTiIsICJSWEkiLCAiRVhJIiwgIklYRyIsICJNWEkiLCAiSVhDIiksIHJlc3BfdmFyID0gIlNQWSIsIHN0YXJ0X2RhdGUgPSAiMjAwNi0wMS0wMSIsIGVuZF9kYXRlID0gIjIwMTAtMTItMzEiLCBudmFsID0gMjUwLCBudGVzdCA9IDI1MCwgbG93X20gPSAxLCBoaWdoX20gPSAxMCwgbG93X3AgPSAxLCBoaWdoX3AgPSAxMCx0YXUgPSAwLjEwLCBwcmludF9tZGwgPSAxLCBwcmludF9tcCA9IDEsIHBhdGggPSAiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9nbG9iX0VURl9ydW5zLyIsIGZpbGVuYW1lID0gInZhcl8xMHBjXzIwMTBfZ2xvYl9ldGYuY3N2IiwgdXZfbGlzdCA9IHZhcl8xMHBjXzIwMTBfdXNldGZbWzFdXSkKYGBgCgojIyMgQ29tbW9kaXR5IEVURnMKCmBgYHtyfQojIDElLCA1JSwgMTAlIFZhUiAtIDIwMTAgLSAzcmQgc2V0IG9mIHByZWRpY3RvcnMKIyB2YXJfMXBjXzIwMTBfY29tbV9ldGYgPSBjYXZfc2ltdWwoYygiREJBIiwgIkRCQyIsICJEQkUiLCAiREJCIiksIHJlc3BfdmFyID0gIlNQWSIsIHN0YXJ0X2RhdGUgPSAiMjAwNi0wMS0wMSIsIGVuZF9kYXRlID0gIjIwMTAtMTItMzEiLCBudmFsID0gMjUwLCBudGVzdCA9IDI1MCwgbG93X20gPSAxLCBoaWdoX20gPSA0LCBsb3dfcCA9IDEsIGhpZ2hfcCA9IDEwLCB0YXUgPSAwLjAxLCBwcmludF9tZGwgPSAxLCBwcmludF9tcCA9IDEsIHBhdGggPSAiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9jb21tX0VURl9ydW5zLyIsIGZpbGVuYW1lID0gInZhcl8xcGNfMjAxMF9jb21tX2V0Zi5jc3YiLCB1dl9saXN0ID0gdmFyXzFwY18yMDEwX3VzZXRmW1sxXV0pCgojIHZhcl81cGNfMjAxMF9jb21tX2V0ZiA9IGNhdl9zaW11bChjKCJEQkEiLCAiREJDIiwgIkRCRSIsICJEQkIiKSwgcmVzcF92YXIgPSAiU1BZIiwgc3RhcnRfZGF0ZSA9ICIyMDA2LTAxLTAxIiwgZW5kX2RhdGUgPSAiMjAxMC0xMi0zMSIsIG52YWwgPSAyNTAsIG50ZXN0ID0gMjUwLCBsb3dfbSA9IDEsIGhpZ2hfbSA9IDQsIGxvd19wID0gMSwgaGlnaF9wID0gMTAsdGF1ID0gMC4wNSwgcHJpbnRfbWRsID0gMSwgcHJpbnRfbXAgPSAxLCBwYXRoID0gIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfY29tbV9FVEZfcnVucy8iLCBmaWxlbmFtZSA9ICJ2YXJfNXBjXzIwMTBfY29tbV9ldGYuY3N2IiwgdXZfbGlzdCA9IHZhcl81cGNfMjAxMF91c2V0ZltbMV1dKQoKIyB2YXJfMTBwY18yMDEwX2NvbW1fZXRmID0gY2F2X3NpbXVsKGMoIkRCQSIsICJEQkMiLCAiREJFIiwgIkRCQiIpLCByZXNwX3ZhciA9ICJTUFkiLCBzdGFydF9kYXRlID0gIjIwMDYtMDEtMDEiLCBlbmRfZGF0ZSA9ICIyMDEwLTEyLTMxIiwgbnZhbCA9IDI1MCwgbnRlc3QgPSAyNTAsIGxvd19tID0gMSwgaGlnaF9tID0gNCwgbG93X3AgPSAxLCBoaWdoX3AgPSAxMCx0YXUgPSAwLjEwLCBwcmludF9tZGwgPSAxLCBwcmludF9tcCA9IDEsIHBhdGggPSAiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9jb21tX0VURl9ydW5zLyIsIGZpbGVuYW1lID0gInZhcl8xMHBjXzIwMTBfY29tbV9ldGYuY3N2IiwgdXZfbGlzdCA9IHZhcl8xMHBjXzIwMTBfdXNldGZbWzFdXSkKYGBgCgojIyMgQm9uZCBFVEZzCgpgYGB7cn0KIyBDYWxsIHRoZSBhYm92ZSBmdW5jdGlvbgp2MV8yMDEwX2JvbmRldGYgPSB2YXJfaW5wdXRfZGlzcCgiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9ib25kX0VURl9ydW5zLyIsInZhcl8xcGNfMjAxMF9ib25kX2V0Zi5jc3YiLCAwLjAxKQp2NV8yMDEwX2JvbmRldGYgPSB2YXJfaW5wdXRfZGlzcCgiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9ib25kX0VURl9ydW5zLyIsInZhcl81cGNfMjAxMF9ib25kX2V0Zi5jc3YiLCAwLjA1KQp2MTBfMjAxMF9ib25kZXRmID0gdmFyX2lucHV0X2Rpc3AoIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfYm9uZF9FVEZfcnVucy8iLCJ2YXJfMTBwY18yMDEwX2JvbmRfZXRmLmNzdiIsIDAuMTApCmBgYAoKQXMgd2l0aCB0aGUgcHJldmlvdXMgdHdvIHJ1bnMsIHRoZSByZXN1bHRzIGZyb20gdGhlIGJvbmQgRVRGcyBhcmUgYmV0dGVyIHRoYW4gdGhvc2UgZnJvbSAyMDA4LgoKYGBge3J9CiMgaVNoYXJlcyAxLTMgWWVhciBUcmVhc3VyeSBCb25kIEZ1bmQgKFNIWSkKIyBpU2hhcmVzIDctMTAgWWVhciBUcmVhc3VyeSBCb25kIEZ1bmQgKElFRikKIyBpU2hhcmVzIDIwKyBZZWFyIFRyZWFzdXJ5IEJvbmQgRnVuZCAoVExUKQojIGlTaGFyZXMgaUJveHggJCBJbnZlc3RtZW50IEdyYWRlIENvcnBvcmF0ZSBCb25kIEVURiAoTFFEKQoKIyAxJSwgNSUsIDEwJSBWYVIgLSAyMDEwIC0gNHRoIHNldCBvZiBwcmVkaWN0b3JzCiMgdmFyXzFwY18yMDEwX2JvbmRfZXRmID0gY2F2X3NpbXVsKGMoIlNIWSIsICJJRUYiLCAiVExUIiwgIkxRRCIpLCByZXNwX3ZhciA9ICJTUFkiLCBzdGFydF9kYXRlID0gIjIwMDYtMDEtMDEiLCBlbmRfZGF0ZSA9ICIyMDEwLTEyLTMxIiwgbnZhbCA9IDI1MCwgbnRlc3QgPSAyNTAsIGxvd19tID0gMSwgaGlnaF9tID0gNCwgbG93X3AgPSAxLCBoaWdoX3AgPSAxMCwgdGF1ID0gMC4wMSwgcHJpbnRfbWRsID0gMSwgcHJpbnRfbXAgPSAxLCBwYXRoID0gIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfYm9uZF9FVEZfcnVucy8iLCBmaWxlbmFtZSA9ICJ2YXJfMXBjXzIwMTBfYm9uZF9ldGYuY3N2IiwgdXZfbGlzdCA9IHZhcl8xcGNfMjAxMF91c2V0ZltbMV1dKQoKIyB2YXJfNXBjXzIwMTBfYm9uZF9ldGYgPSBjYXZfc2ltdWwoYygiU0hZIiwgIklFRiIsICJUTFQiLCAiTFFEIiksIHJlc3BfdmFyID0gIlNQWSIsIHN0YXJ0X2RhdGUgPSAiMjAwNi0wMS0wMSIsIGVuZF9kYXRlID0gIjIwMTAtMTItMzEiLCBudmFsID0gMjUwLCBudGVzdCA9IDI1MCwgbG93X20gPSAxLCBoaWdoX20gPSA0LCBsb3dfcCA9IDEsIGhpZ2hfcCA9IDEwLHRhdSA9IDAuMDUsIHByaW50X21kbCA9IDEsIHByaW50X21wID0gMSwgcGF0aCA9ICIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2JvbmRfRVRGX3J1bnMvIiwgZmlsZW5hbWUgPSAidmFyXzVwY18yMDEwX2JvbmRfZXRmLmNzdiIsIHV2X2xpc3QgPSB2YXJfNXBjXzIwMTBfdXNldGZbWzFdXSkKCiMgdmFyXzEwcGNfMjAxMF9ib25kX2V0ZiA9IGNhdl9zaW11bChjKCJTSFkiLCAiSUVGIiwgIlRMVCIsICJMUUQiKSwgcmVzcF92YXIgPSAiU1BZIiwgc3RhcnRfZGF0ZSA9ICIyMDA2LTAxLTAxIiwgZW5kX2RhdGUgPSAiMjAxMC0xMi0zMSIsIG52YWwgPSAyNTAsIG50ZXN0ID0gMjUwLCBsb3dfbSA9IDEsIGhpZ2hfbSA9IDQsIGxvd19wID0gMSwgaGlnaF9wID0gMTAsdGF1ID0gMC4xMCwgcHJpbnRfbWRsID0gMSwgcHJpbnRfbXAgPSAxLCBwYXRoID0gIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfYm9uZF9FVEZfcnVucy8iLCBmaWxlbmFtZSA9ICJ2YXJfMTBwY18yMDEwX2JvbmRfZXRmLmNzdiIsIHV2X2xpc3QgPSB2YXJfMTBwY18yMDEwX3VzZXRmW1sxXV0pCmBgYAoKIyMjIEFsbCBFVEZzCgpgYGB7cn0KIyBDYWxsIHRoZSBhYm92ZSBmdW5jdGlvbgp2MV8yMDEwX2FsbGV0ZiA9IHZhcl9pbnB1dF9kaXNwKCIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2FsbF9FVEZfcnVucy8iLCJ2YXJfMXBjXzIwMTBfYWxsX2V0Zi5jc3YiLCAwLjAxKQp2NV8yMDEwX2FsbGV0ZiA9IHZhcl9pbnB1dF9kaXNwKCIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2FsbF9FVEZfcnVucy8iLCJ2YXJfNXBjXzIwMTBfYWxsX2V0Zi5jc3YiLCAwLjA1KQp2MTBfMjAxMF9hbGxldGYgPSB2YXJfaW5wdXRfZGlzcCgiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9hbGxfRVRGX3J1bnMvIiwidmFyXzEwcGNfMjAxMF9hbGxfZXRmLmNzdiIsIDAuMTApCmBgYAoKVGhlIGluY2x1c2lvbiBvZiBhbGwgcHJlZGljdG9ycyByZXZlYWxzIHNpbWlsYXIgcmVzdWx0cyBmb3IgdGhlIG11bHRpdmFyaWF0ZSBtb2RlbHMgYXMgdGhlIHByZXZpb3VzIGZvcmVjYXN0czsgdGhlIHJlc3VsdHMgYXJlIGdlbmVyYWxseSBpbi1saW5lIHRoZSB1bml2YXJpYXRlIENBVmlhUiBtb2RlbC4KCmBgYHtyfQojIDElLCA1JSwgMTAlIFZhUiAtIDIwMTAgLSA1dGggc2V0IG9mIHByZWRpY3RvcnMKIyB2YXJfMXBjXzIwMTBfYWxsX2V0ZiA9IGNhdl9zaW11bChjKCJYTFUiLCAiWExQIiwgIlhMViIsICJYTEsiLCAiWExZIiwgIlhMSSIsICJYTEYiLCAiWExCIiwgIlhMRSIsICJKWEkiLCAiS1hJIiwgIklYSiIsICJJWFAiLCAiSVhOIiwgIlJYSSIsICJFWEkiLCAiSVhHIiwgIk1YSSIsICJJWEMiLCAiU0hZIiwgIklFRiIsICJUTFQiLCAiTFFEIiksIHJlc3BfdmFyID0gIlNQWSIsIHN0YXJ0X2RhdGUgPSAiMjAwNi0wMS0wMSIsIGVuZF9kYXRlID0gIjIwMTAtMTItMzEiLCBudmFsID0gMjUwLCBudGVzdCA9IDI1MCwgbG93X20gPSAxLCBoaWdoX20gPSAyMywgbG93X3AgPSAxLCBoaWdoX3AgPSAxMCwgdGF1ID0gMC4wMSwgcHJpbnRfbWRsID0gMSwgcHJpbnRfbXAgPSAxLCBwYXRoID0gIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfYWxsX0VURl9ydW5zLyIsIGZpbGVuYW1lID0gInZhcl8xcGNfMjAxMF9hbGxfZXRmLmNzdiIsIHV2X2xpc3QgPSB2YXJfMXBjXzIwMTBfdXNldGZbWzFdXSkKCiMgdmFyXzVwY18yMDEwX2FsbF9ldGYgPSBjYXZfc2ltdWwoYygiWExVIiwgIlhMUCIsICJYTFYiLCAiWExLIiwgIlhMWSIsICJYTEkiLCAiWExGIiwgIlhMQiIsICJYTEUiLCAiSlhJIiwgIktYSSIsICJJWEoiLCAiSVhQIiwgIklYTiIsICJSWEkiLCAiRVhJIiwgIklYRyIsICJNWEkiLCAiSVhDIiwgIlNIWSIsICJJRUYiLCAiVExUIiwgIkxRRCIpLCByZXNwX3ZhciA9ICJTUFkiLCBzdGFydF9kYXRlID0gIjIwMDYtMDEtMDEiLCBlbmRfZGF0ZSA9ICIyMDEwLTEyLTMxIiwgbnZhbCA9IDI1MCwgbnRlc3QgPSAyNTAsIGxvd19tID0gMSwgaGlnaF9tID0gMjMsIGxvd19wID0gMSwgaGlnaF9wID0gMTAsdGF1ID0gMC4wNSwgcHJpbnRfbWRsID0gMSwgcHJpbnRfbXAgPSAxLCBwYXRoID0gIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfYWxsX0VURl9ydW5zLyIsIGZpbGVuYW1lID0gInZhcl81cGNfMjAxMF9hbGxfZXRmLmNzdiIsIHV2X2xpc3QgPSB2YXJfNXBjXzIwMTBfdXNldGZbWzFdXSkKCiMgdmFyXzEwcGNfMjAxMF9hbGxfZXRmID0gY2F2X3NpbXVsKGMoIlhMVSIsICJYTFAiLCAiWExWIiwgIlhMSyIsICJYTFkiLCAiWExJIiwgIlhMRiIsICJYTEIiLCAiWExFIiwgIkpYSSIsICJLWEkiLCAiSVhKIiwgIklYUCIsICJJWE4iLCAiUlhJIiwgIkVYSSIsICJJWEciLCAiTVhJIiwgIklYQyIsICJTSFkiLCAiSUVGIiwgIlRMVCIsICJMUUQiKSwgcmVzcF92YXIgPSAiU1BZIiwgc3RhcnRfZGF0ZSA9ICIyMDA2LTAxLTAxIiwgZW5kX2RhdGUgPSAiMjAxMC0xMi0zMSIsIG52YWwgPSAyNTAsIG50ZXN0ID0gMjUwLCBsb3dfbSA9IDEsIGhpZ2hfbSA9IDIzLCBsb3dfcCA9IDEsIGhpZ2hfcCA9IDEwLHRhdSA9IDAuMTAsIHByaW50X21kbCA9IDEsIHByaW50X21wID0gMSwgcGF0aCA9ICIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2FsbF9FVEZfcnVucy8iLCBmaWxlbmFtZSA9ICJ2YXJfMTBwY18yMDEwX2FsbF9ldGYuY3N2IiwgdXZfbGlzdCA9IHZhcl8xMHBjXzIwMTBfdXNldGZbWzFdXSkKYGBgCgojIyAyMDE0IEVuZGluZwoKIyMjIFUuUy4gRVRGcwoKYGBge3J9CiMgQ2FsbCB0aGUgYWJvdmUgZnVuY3Rpb24KdjFfMjAxNF91c2V0ZiA9IHZhcl9pbnB1dF9kaXNwKCIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX1VTX0VURl9ydW5zLyIsInZhcl8xcGNfMjAxNF91c19ldGYuY3N2IiwgMC4wMSkKdjVfMjAxNF91c2V0ZiA9IHZhcl9pbnB1dF9kaXNwKCIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX1VTX0VURl9ydW5zLyIsInZhcl81cGNfMjAxNF91c19ldGYuY3N2IiwgMC4wNSkKdjEwXzIwMTRfdXNldGYgPSB2YXJfaW5wdXRfZGlzcCgiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9VU19FVEZfcnVucy8iLCJ2YXJfMTBwY18yMDE0X3VzX2V0Zi5jc3YiLCAwLjEwKQpgYGAKCkFzIHdpdGggdGhlIHJlc3VsdHMgaW4gMjAxNCwgdGhlIHJlc3VsdHMgZnJvbSB0aGUgVS5TLiBFVEZzIHNob3dzIGEgc2ltaWxhciBxdWFsaXR5IG9mIHByZWRpY3Rpb25zLgoKYGBge3J9CiMgMSUsIDUlLCAxMCUgVmFSIC0gMjAxNCAtIDFzdCBzZXQgb2YgcHJlZGljdG9ycwojIHZhcl8xcGNfMjAxNF91c19ldGYgPSBjYXZfc2ltdWwoYygiWExVIiwgIlhMUCIsICJYTFYiLCAiWExLIiwgIlhMWSIsICJYTEkiLCAiWExGIiwgIlhMQiIsICJYTEUiKSwgcmVzcF92YXIgPSAiU1BZIiwgc3RhcnRfZGF0ZSA9ICIyMDEwLTAxLTAxIiwgZW5kX2RhdGUgPSAiMjAxNC0xMi0zMSIsIG52YWwgPSAyNTAsIG50ZXN0ID0gMjUwLCBsb3dfbSA9IDEsIGhpZ2hfbSA9IDksIGxvd19wID0gMSwgaGlnaF9wID0gMTAsIHRhdSA9IDAuMDEsIHByaW50X21kbCA9IDEsIHByaW50X21wID0gMSwgcGF0aCA9ICIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX1VTX0VURl9ydW5zLyIsIGZpbGVuYW1lID0gInZhcl8xcGNfMjAxNF91c19ldGYuY3N2IiwgdXZfbGlzdCA9IHZhcl8xcGNfMjAxNF91c2V0ZltbMV1dKQoKIyB2YXJfNXBjXzIwMTRfdXNfZXRmID0gY2F2X3NpbXVsKGMoIlhMVSIsICJYTFAiLCAiWExWIiwgIlhMSyIsICJYTFkiLCAiWExJIiwgIlhMRiIsICJYTEIiLCAiWExFIiksIHJlc3BfdmFyID0gIlNQWSIsIHN0YXJ0X2RhdGUgPSAiMjAxMC0wMS0wMSIsIGVuZF9kYXRlID0gIjIwMTQtMTItMzEiLCBudmFsID0gMjUwLCBudGVzdCA9IDI1MCwgbG93X20gPSAxLCBoaWdoX20gPSA5LCBsb3dfcCA9IDEsIGhpZ2hfcCA9IDEwLHRhdSA9IDAuMDUsIHByaW50X21kbCA9IDEsIHByaW50X21wID0gMSwgcGF0aCA9ICIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX1VTX0VURl9ydW5zLyIsIGZpbGVuYW1lID0gInZhcl81cGNfMjAxNF91c19ldGYuY3N2IiwgdXZfbGlzdCA9IHZhcl81cGNfMjAxNF91c2V0ZltbMV1dKQoKIyB2YXJfMTBwY18yMDE0X3VzX2V0ZiA9IGNhdl9zaW11bChjKCJYTFUiLCAiWExQIiwgIlhMViIsICJYTEsiLCAiWExZIiwgIlhMSSIsICJYTEYiLCAiWExCIiwgIlhMRSIpLCByZXNwX3ZhciA9ICJTUFkiLCBzdGFydF9kYXRlID0gIjIwMTAtMDEtMDEiLCBlbmRfZGF0ZSA9ICIyMDE0LTEyLTMxIiwgbnZhbCA9IDI1MCwgbnRlc3QgPSAyNTAsIGxvd19tID0gMSwgaGlnaF9tID0gOSwgbG93X3AgPSAxLCBoaWdoX3AgPSAxMCx0YXUgPSAwLjEwLCBwcmludF9tZGwgPSAxLCBwcmludF9tcCA9IDEsIHBhdGggPSAiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9VU19FVEZfcnVucy8iLCBmaWxlbmFtZSA9ICJ2YXJfMTBwY18yMDE0X3VzX2V0Zi5jc3YiLCB1dl9saXN0ID0gdmFyXzEwcGNfMjAxNF91c2V0ZltbMV1dKQpgYGAKCiMjIyBHbG9iYWwgRVRGcwoKYGBge3J9CiMgQ2FsbCB0aGUgYWJvdmUgZnVuY3Rpb24KdjFfMjAxNF9nbG9iZXRmID0gdmFyX2lucHV0X2Rpc3AoIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfZ2xvYl9FVEZfcnVucy8iLCJ2YXJfMXBjXzIwMTRfZ2xvYl9ldGYuY3N2IiwgMC4wMSkKdjVfMjAxNF9nbG9iZXRmID0gdmFyX2lucHV0X2Rpc3AoIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfZ2xvYl9FVEZfcnVucy8iLCJ2YXJfNXBjXzIwMTRfZ2xvYl9ldGYuY3N2IiwgMC4wNSkKdjEwXzIwMTRfZ2xvYmV0ZiA9IHZhcl9pbnB1dF9kaXNwKCIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2dsb2JfRVRGX3J1bnMvIiwidmFyXzEwcGNfMjAxNF9nbG9iX2V0Zi5jc3YiLCAwLjEwKQpgYGAKClRoZSByZXN1bHRzIHNob3cgdGhhdCB0aGUgbXVsdGl2YXJpYXRlIHByZWRpY3Rpb25zIGFyZSBvZiBzaW1pbGFyIHF1YWxpdHkgdG8gdGhlIHByZWRpY3Rpb25zIGZyb20gdGhlIHVuaXZhcmlhdGUgbW9kZWwuIAoKYGBge3J9CiMgMSUsIDUlLCAxMCUgVmFSIC0gMjAxNCAtIDJuZCBzZXQgb2YgcHJlZGljdG9ycwojIHZhcl8xcGNfMjAxNF9nbG9iX2V0ZiA9IGNhdl9zaW11bChjKCJKWEkiLCAiS1hJIiwgIklYSiIsICJJWFAiLCAiSVhOIiwgIlJYSSIsICJFWEkiLCAiSVhHIiwgIk1YSSIsICJJWEMiKSwgcmVzcF92YXIgPSAiU1BZIiwgc3RhcnRfZGF0ZSA9ICIyMDEwLTAxLTAxIiwgZW5kX2RhdGUgPSAiMjAxNC0xMi0zMSIsIG52YWwgPSAyNTAsIG50ZXN0ID0gMjUwLCBsb3dfbSA9IDEsIGhpZ2hfbSA9IDEwLCBsb3dfcCA9IDEsIGhpZ2hfcCA9IDEwLCB0YXUgPSAwLjAxLCBwcmludF9tZGwgPSAxLCBwcmludF9tcCA9IDEsIHBhdGggPSAiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9nbG9iX0VURl9ydW5zLyIsIGZpbGVuYW1lID0gInZhcl8xcGNfMjAxNF9nbG9iX2V0Zi5jc3YiLCB1dl9saXN0ID0gdmFyXzFwY18yMDE0X3VzZXRmW1sxXV0pCgojIHZhcl81cGNfMjAxNF9nbG9iX2V0ZiA9IGNhdl9zaW11bChjKCJKWEkiLCAiS1hJIiwgIklYSiIsICJJWFAiLCAiSVhOIiwgIlJYSSIsICJFWEkiLCAiSVhHIiwgIk1YSSIsICJJWEMiKSwgcmVzcF92YXIgPSAiU1BZIiwgc3RhcnRfZGF0ZSA9ICIyMDEwLTAxLTAxIiwgZW5kX2RhdGUgPSAiMjAxNC0xMi0zMSIsIG52YWwgPSAyNTAsIG50ZXN0ID0gMjUwLCBsb3dfbSA9IDEsIGhpZ2hfbSA9IDEwLCBsb3dfcCA9IDEsIGhpZ2hfcCA9IDEwLHRhdSA9IDAuMDUsIHByaW50X21kbCA9IDEsIHByaW50X21wID0gMSwgcGF0aCA9ICIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2dsb2JfRVRGX3J1bnMvIiwgZmlsZW5hbWUgPSAidmFyXzVwY18yMDE0X2dsb2JfZXRmLmNzdiIsIHV2X2xpc3QgPSB2YXJfNXBjXzIwMTRfdXNldGZbWzFdXSkKCiMgdmFyXzEwcGNfMjAxNF9nbG9iX2V0ZiA9IGNhdl9zaW11bChjKCJKWEkiLCAiS1hJIiwgIklYSiIsICJJWFAiLCAiSVhOIiwgIlJYSSIsICJFWEkiLCAiSVhHIiwgIk1YSSIsICJJWEMiKSwgcmVzcF92YXIgPSAiU1BZIiwgc3RhcnRfZGF0ZSA9ICIyMDEwLTAxLTAxIiwgZW5kX2RhdGUgPSAiMjAxNC0xMi0zMSIsIG52YWwgPSAyNTAsIG50ZXN0ID0gMjUwLCBsb3dfbSA9IDEsIGhpZ2hfbSA9IDEwLCBsb3dfcCA9IDEsIGhpZ2hfcCA9IDEwLHRhdSA9IDAuMTAsIHByaW50X21kbCA9IDEsIHByaW50X21wID0gMSwgcGF0aCA9ICIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2dsb2JfRVRGX3J1bnMvIiwgZmlsZW5hbWUgPSAidmFyXzEwcGNfMjAxNF9nbG9iX2V0Zi5jc3YiLCB1dl9saXN0ID0gdmFyXzEwcGNfMjAxNF91c2V0ZltbMV1dKQpgYGAKCiMjIyBDb21tb2RpdHkgRVRGcwoKYGBge3J9CiMgMSUsIDUlLCAxMCUgVmFSIC0gMjAxNCAtIDNyZCBzZXQgb2YgcHJlZGljdG9ycwojIHZhcl8xcGNfMjAxNF9jb21tX2V0ZiA9IGNhdl9zaW11bChjKCJEQkEiLCAiREJDIiwgIkRCRSIsICJEQkIiKSwgcmVzcF92YXIgPSAiU1BZIiwgc3RhcnRfZGF0ZSA9ICIyMDEwLTAxLTAxIiwgZW5kX2RhdGUgPSAiMjAxNC0xMi0zMSIsIG52YWwgPSAyNTAsIG50ZXN0ID0gMjUwLCBsb3dfbSA9IDEsIGhpZ2hfbSA9IDQsIGxvd19wID0gMSwgaGlnaF9wID0gMTAsIHRhdSA9IDAuMDEsIHByaW50X21kbCA9IDEsIHByaW50X21wID0gMSwgcGF0aCA9ICIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2NvbW1fRVRGX3J1bnMvIiwgZmlsZW5hbWUgPSAidmFyXzFwY18yMDE0X2NvbW1fZXRmLmNzdiIsIHV2X2xpc3QgPSB2YXJfMXBjXzIwMTRfdXNldGZbWzFdXSkKCiMgdmFyXzVwY18yMDE0X2NvbW1fZXRmID0gY2F2X3NpbXVsKGMoIkRCQSIsICJEQkMiLCAiREJFIiwgIkRCQiIpLCByZXNwX3ZhciA9ICJTUFkiLCBzdGFydF9kYXRlID0gIjIwMTAtMDEtMDEiLCBlbmRfZGF0ZSA9ICIyMDE0LTEyLTMxIiwgbnZhbCA9IDI1MCwgbnRlc3QgPSAyNTAsIGxvd19tID0gMSwgaGlnaF9tID0gNCwgbG93X3AgPSAxLCBoaWdoX3AgPSAxMCx0YXUgPSAwLjA1LCBwcmludF9tZGwgPSAxLCBwcmludF9tcCA9IDEsIHBhdGggPSAiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9jb21tX0VURl9ydW5zLyIsIGZpbGVuYW1lID0gInZhcl81cGNfMjAxNF9jb21tX2V0Zi5jc3YiLCB1dl9saXN0ID0gdmFyXzVwY18yMDE0X3VzZXRmW1sxXV0pCgojIHZhcl8xMHBjXzIwMTRfY29tbV9ldGYgPSBjYXZfc2ltdWwoYygiREJBIiwgIkRCQyIsICJEQkUiLCAiREJCIiksIHJlc3BfdmFyID0gIlNQWSIsIHN0YXJ0X2RhdGUgPSAiMjAxMC0wMS0wMSIsIGVuZF9kYXRlID0gIjIwMTQtMTItMzEiLCBudmFsID0gMjUwLCBudGVzdCA9IDI1MCwgbG93X20gPSAxLCBoaWdoX20gPSA0LCBsb3dfcCA9IDEsIGhpZ2hfcCA9IDEwLHRhdSA9IDAuMTAsIHByaW50X21kbCA9IDEsIHByaW50X21wID0gMSwgcGF0aCA9ICIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2NvbW1fRVRGX3J1bnMvIiwgZmlsZW5hbWUgPSAidmFyXzEwcGNfMjAxNF9jb21tX2V0Zi5jc3YiLCB1dl9saXN0ID0gdmFyXzEwcGNfMjAxNF91c2V0ZltbMV1dKQpgYGAKCiMjIyBCb25kIEVURnMKCmBgYHtyfQojIENhbGwgdGhlIGFib3ZlIGZ1bmN0aW9uCnYxXzIwMTRfYm9uZGV0ZiA9IHZhcl9pbnB1dF9kaXNwKCIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2JvbmRfRVRGX3J1bnMvIiwidmFyXzFwY18yMDE0X2JvbmRfZXRmLmNzdiIsIDAuMDEpCnY1XzIwMTRfYm9uZGV0ZiA9IHZhcl9pbnB1dF9kaXNwKCIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2JvbmRfRVRGX3J1bnMvIiwidmFyXzVwY18yMDE0X2JvbmRfZXRmLmNzdiIsIDAuMDUpCnYxMF8yMDE0X2JvbmRldGYgPSB2YXJfaW5wdXRfZGlzcCgiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9ib25kX0VURl9ydW5zLyIsInZhcl8xMHBjXzIwMTRfYm9uZF9ldGYuY3N2IiwgMC4xMCkKYGBgCgpBcyB3aXRoIHRoZSBvdGhlciB0d28gc2V0cyBvZiByZWdyZXNzb3JzLCB0aGUgcmVzdWx0cyBoZXJlIHNob3cgdGhhdCB0aGUgbXVsdGl2YXJpYXRlIHByZWRpY3Rpb25zIGFyZSBvZiBzaW1pbGFyIHF1YWxpdHkgdG8gdGhlIHByZWRpY3Rpb25zIGZyb20gdGhlIHVuaXZhcmlhdGUgbW9kZWwuIAoKYGBge3J9CiMgaVNoYXJlcyAxLTMgWWVhciBUcmVhc3VyeSBCb25kIEZ1bmQgKFNIWSkKIyBpU2hhcmVzIDctMTAgWWVhciBUcmVhc3VyeSBCb25kIEZ1bmQgKElFRikKIyBpU2hhcmVzIDIwKyBZZWFyIFRyZWFzdXJ5IEJvbmQgRnVuZCAoVExUKQojIGlTaGFyZXMgaUJveHggJCBJbnZlc3RtZW50IEdyYWRlIENvcnBvcmF0ZSBCb25kIEVURiAoTFFEKQoKIyAxJSwgNSUsIDEwJSBWYVIgLSAyMDE0IC0gNHRoIHNldCBvZiBwcmVkaWN0b3JzCiMgdmFyXzFwY18yMDE0X2JvbmRfZXRmID0gY2F2X3NpbXVsKGMoIlNIWSIsICJJRUYiLCAiVExUIiwgIkxRRCIpLCByZXNwX3ZhciA9ICJTUFkiLCBzdGFydF9kYXRlID0gIjIwMTAtMDEtMDEiLCBlbmRfZGF0ZSA9ICIyMDE0LTEyLTMxIiwgbnZhbCA9IDI1MCwgbnRlc3QgPSAyNTAsIGxvd19tID0gMSwgaGlnaF9tID0gNCwgbG93X3AgPSAxLCBoaWdoX3AgPSAxMCwgdGF1ID0gMC4wMSwgcHJpbnRfbWRsID0gMSwgcHJpbnRfbXAgPSAxLCBwYXRoID0gIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfYm9uZF9FVEZfcnVucy8iLCBmaWxlbmFtZSA9ICJ2YXJfMXBjXzIwMTRfYm9uZF9ldGYuY3N2IiwgdXZfbGlzdCA9IHZhcl8xcGNfMjAxNF91c2V0ZltbMV1dKQoKIyB2YXJfNXBjXzIwMTRfYm9uZF9ldGYgPSBjYXZfc2ltdWwoYygiU0hZIiwgIklFRiIsICJUTFQiLCAiTFFEIiksIHJlc3BfdmFyID0gIlNQWSIsIHN0YXJ0X2RhdGUgPSAiMjAxMC0wMS0wMSIsIGVuZF9kYXRlID0gIjIwMTQtMTItMzEiLCBudmFsID0gMjUwLCBudGVzdCA9IDI1MCwgbG93X20gPSAxLCBoaWdoX20gPSA0LCBsb3dfcCA9IDEsIGhpZ2hfcCA9IDEwLHRhdSA9IDAuMDUsIHByaW50X21kbCA9IDEsIHByaW50X21wID0gMSwgcGF0aCA9ICIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2JvbmRfRVRGX3J1bnMvIiwgZmlsZW5hbWUgPSAidmFyXzVwY18yMDE0X2JvbmRfZXRmLmNzdiIsIHV2X2xpc3QgPSB2YXJfNXBjXzIwMTRfdXNldGZbWzFdXSkKCiMgdmFyXzEwcGNfMjAxNF9ib25kX2V0ZiA9IGNhdl9zaW11bChjKCJTSFkiLCAiSUVGIiwgIlRMVCIsICJMUUQiKSwgcmVzcF92YXIgPSAiU1BZIiwgc3RhcnRfZGF0ZSA9ICIyMDEwLTAxLTAxIiwgZW5kX2RhdGUgPSAiMjAxNC0xMi0zMSIsIG52YWwgPSAyNTAsIG50ZXN0ID0gMjUwLCBsb3dfbSA9IDEsIGhpZ2hfbSA9IDQsIGxvd19wID0gMSwgaGlnaF9wID0gMTAsdGF1ID0gMC4xMCwgcHJpbnRfbWRsID0gMSwgcHJpbnRfbXAgPSAxLCBwYXRoID0gIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfYm9uZF9FVEZfcnVucy8iLCBmaWxlbmFtZSA9ICJ2YXJfMTBwY18yMDE0X2JvbmRfZXRmLmNzdiIsIHV2X2xpc3QgPSB2YXJfMTBwY18yMDE0X3VzZXRmW1sxXV0pCmBgYAoKIyMjIEFsbCBFVEZzCgpgYGB7cn0KIyBDYWxsIHRoZSBhYm92ZSBmdW5jdGlvbgp2MV8yMDE0X2FsbGV0ZiA9IHZhcl9pbnB1dF9kaXNwKCIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2FsbF9FVEZfcnVucy8iLCJ2YXJfMXBjXzIwMTRfYWxsX2V0Zi5jc3YiLCAwLjAxKQp2NV8yMDE0X2FsbGV0ZiA9IHZhcl9pbnB1dF9kaXNwKCIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2FsbF9FVEZfcnVucy8iLCJ2YXJfNXBjXzIwMTRfYWxsX2V0Zi5jc3YiLCAwLjA1KQp2MTBfMjAxNF9hbGxldGYgPSB2YXJfaW5wdXRfZGlzcCgiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9hbGxfRVRGX3J1bnMvIiwidmFyXzEwcGNfMjAxNF9hbGxfZXRmLmNzdiIsIDAuMTApCmBgYAoKSW5jbHVkaW5nIGFsbCB0aGUgRVRGcyBhcyByZWdyZXNzb3JzIHByb3ZpZGVzIGEgbXVsdGl2YXJpYXRlIGZvcmVjYXN0IHdpdGggc2ltaWxhciBhY2N1cmFjeSB0byB0aGF0IG9mIHRoZSB1bml2YXJpYXRlIG1vZGVsLiAKCmBgYHtyfQojIDElLCA1JSwgMTAlIFZhUiAtIDIwMTQgLSA1dGggc2V0IG9mIHByZWRpY3RvcnMKIyB2YXJfMXBjXzIwMTRfYWxsX2V0ZiA9IGNhdl9zaW11bChjKCJYTFUiLCAiWExQIiwgIlhMViIsICJYTEsiLCAiWExZIiwgIlhMSSIsICJYTEYiLCAiWExCIiwgIlhMRSIsICJKWEkiLCAiS1hJIiwgIklYSiIsICJJWFAiLCAiSVhOIiwgIlJYSSIsICJFWEkiLCAiSVhHIiwgIk1YSSIsICJJWEMiLCAiU0hZIiwgIklFRiIsICJUTFQiLCAiTFFEIiksIHJlc3BfdmFyID0gIlNQWSIsIHN0YXJ0X2RhdGUgPSAiMjAxMC0wMS0wMSIsIGVuZF9kYXRlID0gIjIwMTQtMTItMzEiLCBudmFsID0gMjUwLCBudGVzdCA9IDI1MCwgbG93X20gPSAxLCBoaWdoX20gPSAyMywgbG93X3AgPSAxLCBoaWdoX3AgPSAxMCwgdGF1ID0gMC4wMSwgcHJpbnRfbWRsID0gMSwgcHJpbnRfbXAgPSAxLCBwYXRoID0gIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfYWxsX0VURl9ydW5zLyIsIGZpbGVuYW1lID0gInZhcl8xcGNfMjAxNF9hbGxfZXRmLmNzdiIsIHV2X2xpc3QgPSB2YXJfMXBjXzIwMTRfdXNldGZbWzFdXSkKCiMgdmFyXzVwY18yMDE0X2FsbF9ldGYgPSBjYXZfc2ltdWwoYygiWExVIiwgIlhMUCIsICJYTFYiLCAiWExLIiwgIlhMWSIsICJYTEkiLCAiWExGIiwgIlhMQiIsICJYTEUiLCAiSlhJIiwgIktYSSIsICJJWEoiLCAiSVhQIiwgIklYTiIsICJSWEkiLCAiRVhJIiwgIklYRyIsICJNWEkiLCAiSVhDIiwgIlNIWSIsICJJRUYiLCAiVExUIiwgIkxRRCIpLCByZXNwX3ZhciA9ICJTUFkiLCBzdGFydF9kYXRlID0gIjIwMTAtMDEtMDEiLCBlbmRfZGF0ZSA9ICIyMDE0LTEyLTMxIiwgbnZhbCA9IDI1MCwgbnRlc3QgPSAyNTAsIGxvd19tID0gMSwgaGlnaF9tID0gMjMsIGxvd19wID0gMSwgaGlnaF9wID0gMTAsdGF1ID0gMC4wNSwgcHJpbnRfbWRsID0gMSwgcHJpbnRfbXAgPSAxLCBwYXRoID0gIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfYWxsX0VURl9ydW5zLyIsIGZpbGVuYW1lID0gInZhcl81cGNfMjAxNF9hbGxfZXRmLmNzdiIsIHV2X2xpc3QgPSB2YXJfNXBjXzIwMTRfdXNldGZbWzFdXSkKCiMgdmFyXzEwcGNfMjAxNF9hbGxfZXRmID0gY2F2X3NpbXVsKGMoIlhMVSIsICJYTFAiLCAiWExWIiwgIlhMSyIsICJYTFkiLCAiWExJIiwgIlhMRiIsICJYTEIiLCAiWExFIiwgIkpYSSIsICJLWEkiLCAiSVhKIiwgIklYUCIsICJJWE4iLCAiUlhJIiwgIkVYSSIsICJJWEciLCAiTVhJIiwgIklYQyIsICJTSFkiLCAiSUVGIiwgIlRMVCIsICJMUUQiKSwgcmVzcF92YXIgPSAiU1BZIiwgc3RhcnRfZGF0ZSA9ICIyMDEwLTAxLTAxIiwgZW5kX2RhdGUgPSAiMjAxNC0xMi0zMSIsIG52YWwgPSAyNTAsIG50ZXN0ID0gMjUwLCBsb3dfbSA9IDEsIGhpZ2hfbSA9IDIzLCBsb3dfcCA9IDEsIGhpZ2hfcCA9IDEwLHRhdSA9IDAuMTAsIHByaW50X21kbCA9IDEsIHByaW50X21wID0gMSwgcGF0aCA9ICIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2FsbF9FVEZfcnVucy8iLCBmaWxlbmFtZSA9ICJ2YXJfMTBwY18yMDE0X2FsbF9ldGYuY3N2IiwgdXZfbGlzdCA9IHZhcl8xMHBjXzIwMTRfdXNldGZbWzFdXSkKYGBgCgoKIyMgMjAxNiBFbmRpbmcKCiMjIyBVLlMuIEVURnMKCmBgYHtyfQojIENhbGwgdGhlIGFib3ZlIGZ1bmN0aW9uCnYxXzIwMTZfdXNldGYgPSB2YXJfaW5wdXRfZGlzcCgiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9VU19FVEZfcnVucy8iLCJ2YXJfMXBjXzIwMTZfdXNfZXRmLmNzdiIsIDAuMDEpCnY1XzIwMTZfdXNldGYgPSB2YXJfaW5wdXRfZGlzcCgiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9VU19FVEZfcnVucy8iLCJ2YXJfNXBjXzIwMTZfdXNfZXRmLmNzdiIsIDAuMDUpCnYxMF8yMDE2X3VzZXRmID0gdmFyX2lucHV0X2Rpc3AoIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfVVNfRVRGX3J1bnMvIiwidmFyXzEwcGNfMjAxNl91c19ldGYuY3N2IiwgMC4xMCkKYGBgCgpBcyB3aXRoIHRoZSBmb3JlY2FzdCBpbiAyMDEwIGFuZCAyMDE0LCBpbmNsdWRpbmcgdGhlIFUuUy4gRVRGcyBhcyBwcmVkaWN0b3JzIGluIHRoZSBtdWx0aXZhcmlhdGUgbW9kZWwgZ2l2ZXMgc2ltaWxhciByZXN1bHRzIHRvIHRoYXQgb2YgdGhlIHVuaXZhcmlhdGUgbW9kZWwuCgpgYGB7cn0KIyAxJSwgNSUsIDEwJSBWYVIgLSAyMDE2IC0gMXN0IHNldCBvZiBwcmVkaWN0b3JzCiMgdmFyXzFwY18yMDE2X3VzX2V0ZiA9IGNhdl9zaW11bChjKCJYTFUiLCAiWExQIiwgIlhMViIsICJYTEsiLCAiWExZIiwgIlhMSSIsICJYTEYiLCAiWExCIiwgIlhMRSIpLCByZXNwX3ZhciA9ICJTUFkiLCBzdGFydF9kYXRlID0gIjIwMTItMDEtMDEiLCBlbmRfZGF0ZSA9ICIyMDE2LTEyLTMxIiwgbnZhbCA9IDI1MCwgbnRlc3QgPSAyNTAsIGxvd19tID0gMSwgaGlnaF9tID0gOSwgbG93X3AgPSAxLCBoaWdoX3AgPSAxMCwgdGF1ID0gMC4wMSwgcHJpbnRfbWRsID0gMSwgcHJpbnRfbXAgPSAxLCBwYXRoID0gIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfVVNfRVRGX3J1bnMvIiwgZmlsZW5hbWUgPSAidmFyXzFwY18yMDE2X3VzX2V0Zi5jc3YiLCB1dl9saXN0ID0gdmFyXzFwY18yMDE2X3VzZXRmW1sxXV0pCgojIHZhcl81cGNfMjAxNl91c19ldGYgPSBjYXZfc2ltdWwoYygiWExVIiwgIlhMUCIsICJYTFYiLCAiWExLIiwgIlhMWSIsICJYTEkiLCAiWExGIiwgIlhMQiIsICJYTEUiKSwgcmVzcF92YXIgPSAiU1BZIiwgc3RhcnRfZGF0ZSA9ICIyMDEyLTAxLTAxIiwgZW5kX2RhdGUgPSAiMjAxNi0xMi0zMSIsIG52YWwgPSAyNTAsIG50ZXN0ID0gMjUwLCBsb3dfbSA9IDEsIGhpZ2hfbSA9IDksIGxvd19wID0gMSwgaGlnaF9wID0gMTAsdGF1ID0gMC4wNSwgcHJpbnRfbWRsID0gMSwgcHJpbnRfbXAgPSAxLCBwYXRoID0gIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfVVNfRVRGX3J1bnMvIiwgZmlsZW5hbWUgPSAidmFyXzVwY18yMDE2X3VzX2V0Zi5jc3YiLCB1dl9saXN0ID0gdmFyXzVwY18yMDE2X3VzZXRmW1sxXV0pCgojIHZhcl8xMHBjXzIwMTZfdXNfZXRmID0gY2F2X3NpbXVsKGMoIlhMVSIsICJYTFAiLCAiWExWIiwgIlhMSyIsICJYTFkiLCAiWExJIiwgIlhMRiIsICJYTEIiLCAiWExFIiksIHJlc3BfdmFyID0gIlNQWSIsIHN0YXJ0X2RhdGUgPSAiMjAxMi0wMS0wMSIsIGVuZF9kYXRlID0gIjIwMTYtMTItMzEiLCBudmFsID0gMjUwLCBudGVzdCA9IDI1MCwgbG93X20gPSAxLCBoaWdoX20gPSA5LCBsb3dfcCA9IDEsIGhpZ2hfcCA9IDEwLHRhdSA9IDAuMTAsIHByaW50X21kbCA9IDEsIHByaW50X21wID0gMSwgcGF0aCA9ICIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX1VTX0VURl9ydW5zLyIsIGZpbGVuYW1lID0gInZhcl8xMHBjXzIwMTZfdXNfZXRmLmNzdiIsIHV2X2xpc3QgPSB2YXJfMTBwY18yMDE2X3VzZXRmW1sxXV0pCmBgYAoKIyMjIEdsb2JhbCBFVEZzCgpgYGB7cn0KIyBDYWxsIHRoZSBhYm92ZSBmdW5jdGlvbgp2MV8yMDE2X2dsb2JldGYgPSB2YXJfaW5wdXRfZGlzcCgiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9nbG9iX0VURl9ydW5zLyIsInZhcl8xcGNfMjAxNl9nbG9iX2V0Zi5jc3YiLCAwLjAxKQp2NV8yMDE2X2dsb2JldGYgPSB2YXJfaW5wdXRfZGlzcCgiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9nbG9iX0VURl9ydW5zLyIsInZhcl81cGNfMjAxNl9nbG9iX2V0Zi5jc3YiLCAwLjA1KQp2MTBfMjAxNl9nbG9iZXRmID0gdmFyX2lucHV0X2Rpc3AoIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfZ2xvYl9FVEZfcnVucy8iLCJ2YXJfMTBwY18yMDE2X2dsb2JfZXRmLmNzdiIsIDAuMTApCmBgYAoKVGhlIGdsb2JhbCBFVEZzIGFzIHByZWRpY3RvcnMgcHJvdmlkZSBzb2xpZCByZXN1bHRzIGFzIHdlbGwuCgpgYGB7cn0KIyAxJSwgNSUsIDEwJSBWYVIgLSAyMDE2IC0gMm5kIHNldCBvZiBwcmVkaWN0b3JzCiMgdmFyXzFwY18yMDE2X2dsb2JfZXRmID0gY2F2X3NpbXVsKGMoIkpYSSIsICJLWEkiLCAiSVhKIiwgIklYUCIsICJJWE4iLCAiUlhJIiwgIkVYSSIsICJJWEciLCAiTVhJIiwgIklYQyIpLCByZXNwX3ZhciA9ICJTUFkiLCBzdGFydF9kYXRlID0gIjIwMTItMDEtMDEiLCBlbmRfZGF0ZSA9ICIyMDE2LTEyLTMxIiwgbnZhbCA9IDI1MCwgbnRlc3QgPSAyNTAsIGxvd19tID0gMSwgaGlnaF9tID0gMTAsIGxvd19wID0gMSwgaGlnaF9wID0gMTAsIHRhdSA9IDAuMDEsIHByaW50X21kbCA9IDEsIHByaW50X21wID0gMSwgcGF0aCA9ICIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2dsb2JfRVRGX3J1bnMvIiwgZmlsZW5hbWUgPSAidmFyXzFwY18yMDE2X2dsb2JfZXRmLmNzdiIsIHV2X2xpc3QgPSB2YXJfMXBjXzIwMTZfdXNldGZbWzFdXSkKCiMgdmFyXzVwY18yMDE2X2dsb2JfZXRmID0gY2F2X3NpbXVsKGMoIkpYSSIsICJLWEkiLCAiSVhKIiwgIklYUCIsICJJWE4iLCAiUlhJIiwgIkVYSSIsICJJWEciLCAiTVhJIiwgIklYQyIpLCByZXNwX3ZhciA9ICJTUFkiLCBzdGFydF9kYXRlID0gIjIwMTItMDEtMDEiLCBlbmRfZGF0ZSA9ICIyMDE2LTEyLTMxIiwgbnZhbCA9IDI1MCwgbnRlc3QgPSAyNTAsIGxvd19tID0gMSwgaGlnaF9tID0gMTAsIGxvd19wID0gMSwgaGlnaF9wID0gMTAsdGF1ID0gMC4wNSwgcHJpbnRfbWRsID0gMSwgcHJpbnRfbXAgPSAxLCBwYXRoID0gIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfZ2xvYl9FVEZfcnVucy8iLCBmaWxlbmFtZSA9ICJ2YXJfNXBjXzIwMTZfZ2xvYl9ldGYuY3N2IiwgdXZfbGlzdCA9IHZhcl81cGNfMjAxNl91c2V0ZltbMV1dKQoKIyB2YXJfMTBwY18yMDE2X2dsb2JfZXRmID0gY2F2X3NpbXVsKGMoIkpYSSIsICJLWEkiLCAiSVhKIiwgIklYUCIsICJJWE4iLCAiUlhJIiwgIkVYSSIsICJJWEciLCAiTVhJIiwgIklYQyIpLCByZXNwX3ZhciA9ICJTUFkiLCBzdGFydF9kYXRlID0gIjIwMTItMDEtMDEiLCBlbmRfZGF0ZSA9ICIyMDE2LTEyLTMxIiwgbnZhbCA9IDI1MCwgbnRlc3QgPSAyNTAsIGxvd19tID0gMSwgaGlnaF9tID0gMTAsIGxvd19wID0gMSwgaGlnaF9wID0gMTAsdGF1ID0gMC4xMCwgcHJpbnRfbWRsID0gMSwgcHJpbnRfbXAgPSAxLCBwYXRoID0gIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfZ2xvYl9FVEZfcnVucy8iLCBmaWxlbmFtZSA9ICJ2YXJfMTBwY18yMDE2X2dsb2JfZXRmLmNzdiIsIHV2X2xpc3QgPSB2YXJfMTBwY18yMDE2X3VzZXRmW1sxXV0pCmBgYAoKIyMjIENvbW1vZGl0eSBFVEZzCgpgYGB7cn0KIyAxJSwgNSUsIDEwJSBWYVIgLSAyMDE2IC0gM3JkIHNldCBvZiBwcmVkaWN0b3JzCiMgdmFyXzFwY18yMDE2X2NvbW1fZXRmID0gY2F2X3NpbXVsKGMoIkRCQSIsICJEQkMiLCAiREJFIiwgIkRCQiIpLCByZXNwX3ZhciA9ICJTUFkiLCBzdGFydF9kYXRlID0gIjIwMTItMDEtMDEiLCBlbmRfZGF0ZSA9ICIyMDE2LTEyLTMxIiwgbnZhbCA9IDI1MCwgbnRlc3QgPSAyNTAsIGxvd19tID0gMSwgaGlnaF9tID0gNCwgbG93X3AgPSAxLCBoaWdoX3AgPSAxMCwgdGF1ID0gMC4wMSwgcHJpbnRfbWRsID0gMSwgcHJpbnRfbXAgPSAxLCBwYXRoID0gIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfY29tbV9FVEZfcnVucy8iLCBmaWxlbmFtZSA9ICJ2YXJfMXBjXzIwMTZfY29tbV9ldGYuY3N2IiwgdXZfbGlzdCA9IHZhcl8xcGNfMjAxNl91c2V0ZltbMV1dKQoKIyB2YXJfNXBjXzIwMTZfY29tbV9ldGYgPSBjYXZfc2ltdWwoYygiREJBIiwgIkRCQyIsICJEQkUiLCAiREJCIiksIHJlc3BfdmFyID0gIlNQWSIsIHN0YXJ0X2RhdGUgPSAiMjAxMi0wMS0wMSIsIGVuZF9kYXRlID0gIjIwMTYtMTItMzEiLCBudmFsID0gMjUwLCBudGVzdCA9IDI1MCwgbG93X20gPSAxLCBoaWdoX20gPSA0LCBsb3dfcCA9IDEsIGhpZ2hfcCA9IDEwLHRhdSA9IDAuMDUsIHByaW50X21kbCA9IDEsIHByaW50X21wID0gMSwgcGF0aCA9ICIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2NvbW1fRVRGX3J1bnMvIiwgZmlsZW5hbWUgPSAidmFyXzVwY18yMDE2X2NvbW1fZXRmLmNzdiIsIHV2X2xpc3QgPSB2YXJfNXBjXzIwMTZfdXNldGZbWzFdXSkKCiMgdmFyXzEwcGNfMjAxNl9jb21tX2V0ZiA9IGNhdl9zaW11bChjKCJEQkEiLCAiREJDIiwgIkRCRSIsICJEQkIiKSwgcmVzcF92YXIgPSAiU1BZIiwgc3RhcnRfZGF0ZSA9ICIyMDEyLTAxLTAxIiwgZW5kX2RhdGUgPSAiMjAxNi0xMi0zMSIsIG52YWwgPSAyNTAsIG50ZXN0ID0gMjUwLCBsb3dfbSA9IDEsIGhpZ2hfbSA9IDQsIGxvd19wID0gMSwgaGlnaF9wID0gMTAsdGF1ID0gMC4xMCwgcHJpbnRfbWRsID0gMSwgcHJpbnRfbXAgPSAxLCBwYXRoID0gIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfY29tbV9FVEZfcnVucy8iLCBmaWxlbmFtZSA9ICJ2YXJfMTBwY18yMDE2X2NvbW1fZXRmLmNzdiIsIHV2X2xpc3QgPSB2YXJfMTBwY18yMDE2X3VzZXRmW1sxXV0pCmBgYAoKIyMjIEJvbmQgRVRGcwoKYGBge3J9CiMgQ2FsbCB0aGUgYWJvdmUgZnVuY3Rpb24KdjFfMjAxNl9ib25kZXRmID0gdmFyX2lucHV0X2Rpc3AoIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfYm9uZF9FVEZfcnVucy8iLCJ2YXJfMXBjXzIwMTZfYm9uZF9ldGYuY3N2IiwgMC4wMSkKdjVfMjAxNl9ib25kZXRmID0gdmFyX2lucHV0X2Rpc3AoIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfYm9uZF9FVEZfcnVucy8iLCJ2YXJfNXBjXzIwMTZfYm9uZF9ldGYuY3N2IiwgMC4wNSkKdjEwXzIwMTZfYm9uZGV0ZiA9IHZhcl9pbnB1dF9kaXNwKCIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2JvbmRfRVRGX3J1bnMvIiwidmFyXzEwcGNfMjAxNl9ib25kX2V0Zi5jc3YiLCAwLjEwKQpgYGAKCkFzIHdpdGggdGhlIFUuUy4gYW5kIEdsb2JhbCBFVEZzLCB0aGUgYm9uZCBFVEZzIHByb3ZpZGUgZ29vZCByZXN1bHRzLgoKYGBge3J9CiMgaVNoYXJlcyAxLTMgWWVhciBUcmVhc3VyeSBCb25kIEZ1bmQgKFNIWSkKIyBpU2hhcmVzIDctMTAgWWVhciBUcmVhc3VyeSBCb25kIEZ1bmQgKElFRikKIyBpU2hhcmVzIDIwKyBZZWFyIFRyZWFzdXJ5IEJvbmQgRnVuZCAoVExUKQojIGlTaGFyZXMgaUJveHggJCBJbnZlc3RtZW50IEdyYWRlIENvcnBvcmF0ZSBCb25kIEVURiAoTFFEKQoKIyAxJSwgNSUsIDEwJSBWYVIgLSAyMDE2IC0gNHRoIHNldCBvZiBwcmVkaWN0b3JzCiMgdmFyXzFwY18yMDE2X2JvbmRfZXRmID0gY2F2X3NpbXVsKGMoIlNIWSIsICJJRUYiLCAiVExUIiwgIkxRRCIpLCByZXNwX3ZhciA9ICJTUFkiLCBzdGFydF9kYXRlID0gIjIwMTItMDEtMDEiLCBlbmRfZGF0ZSA9ICIyMDE2LTEyLTMxIiwgbnZhbCA9IDI1MCwgbnRlc3QgPSAyNTAsIGxvd19tID0gMSwgaGlnaF9tID0gNCwgbG93X3AgPSAxLCBoaWdoX3AgPSAxMCwgdGF1ID0gMC4wMSwgcHJpbnRfbWRsID0gMSwgcHJpbnRfbXAgPSAxLCBwYXRoID0gIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfYm9uZF9FVEZfcnVucy8iLCBmaWxlbmFtZSA9ICJ2YXJfMXBjXzIwMTZfYm9uZF9ldGYuY3N2IiwgdXZfbGlzdCA9IHZhcl8xcGNfMjAxNl91c2V0ZltbMV1dKQoKIyB2YXJfNXBjXzIwMTZfYm9uZF9ldGYgPSBjYXZfc2ltdWwoYygiU0hZIiwgIklFRiIsICJUTFQiLCAiTFFEIiksIHJlc3BfdmFyID0gIlNQWSIsIHN0YXJ0X2RhdGUgPSAiMjAxMi0wMS0wMSIsIGVuZF9kYXRlID0gIjIwMTYtMTItMzEiLCBudmFsID0gMjUwLCBudGVzdCA9IDI1MCwgbG93X20gPSAxLCBoaWdoX20gPSA0LCBsb3dfcCA9IDEsIGhpZ2hfcCA9IDEwLHRhdSA9IDAuMDUsIHByaW50X21kbCA9IDEsIHByaW50X21wID0gMSwgcGF0aCA9ICIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2JvbmRfRVRGX3J1bnMvIiwgZmlsZW5hbWUgPSAidmFyXzVwY18yMDE2X2JvbmRfZXRmLmNzdiIsIHV2X2xpc3QgPSB2YXJfNXBjXzIwMTZfdXNldGZbWzFdXSkKCiMgdmFyXzEwcGNfMjAxNl9ib25kX2V0ZiA9IGNhdl9zaW11bChjKCJTSFkiLCAiSUVGIiwgIlRMVCIsICJMUUQiKSwgcmVzcF92YXIgPSAiU1BZIiwgc3RhcnRfZGF0ZSA9ICIyMDEyLTAxLTAxIiwgZW5kX2RhdGUgPSAiMjAxNi0xMi0zMSIsIG52YWwgPSAyNTAsIG50ZXN0ID0gMjUwLCBsb3dfbSA9IDEsIGhpZ2hfbSA9IDQsIGxvd19wID0gMSwgaGlnaF9wID0gMTAsdGF1ID0gMC4xMCwgcHJpbnRfbWRsID0gMSwgcHJpbnRfbXAgPSAxLCBwYXRoID0gIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfYm9uZF9FVEZfcnVucy8iLCBmaWxlbmFtZSA9ICJ2YXJfMTBwY18yMDE2X2JvbmRfZXRmLmNzdiIsIHV2X2xpc3QgPSB2YXJfMTBwY18yMDE2X3VzZXRmW1sxXV0pCmBgYAoKIyMjIEFsbCBFVEZzCgpgYGB7cn0KIyBDYWxsIHRoZSBhYm92ZSBmdW5jdGlvbgp2MV8yMDE2X2FsbGV0ZiA9IHZhcl9pbnB1dF9kaXNwKCIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2FsbF9FVEZfcnVucy8iLCJ2YXJfMXBjXzIwMTZfYWxsX2V0Zi5jc3YiLCAwLjAxKQp2NV8yMDE2X2FsbGV0ZiA9IHZhcl9pbnB1dF9kaXNwKCIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2FsbF9FVEZfcnVucy8iLCJ2YXJfNXBjXzIwMTZfYWxsX2V0Zi5jc3YiLCAwLjA1KQp2MTBfMjAxNl9hbGxldGYgPSB2YXJfaW5wdXRfZGlzcCgiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9hbGxfRVRGX3J1bnMvIiwidmFyXzEwcGNfMjAxNl9hbGxfZXRmLmNzdiIsIDAuMTApCmBgYAoKSW5jbHVkaW5nIGFsbCBFVEZzIGFzIHByZWRpY3RvcnMgeWllbGRzIGdvb2QgcXVhbGl0eSByZXN1bHRzIGZvciB0aGUgMjAxNiB0ZXN0IHBlcmlvZC4KCmBgYHtyfQojIDElLCA1JSwgMTAlIFZhUiAtIDIwMTYgLSA1dGggc2V0IG9mIHByZWRpY3RvcnMKIyB2YXJfMXBjXzIwMTZfYWxsX2V0ZiA9IGNhdl9zaW11bChjKCJYTFUiLCAiWExQIiwgIlhMViIsICJYTEsiLCAiWExZIiwgIlhMSSIsICJYTEYiLCAiWExCIiwgIlhMRSIsICJKWEkiLCAiS1hJIiwgIklYSiIsICJJWFAiLCAiSVhOIiwgIlJYSSIsICJFWEkiLCAiSVhHIiwgIk1YSSIsICJJWEMiLCAiU0hZIiwgIklFRiIsICJUTFQiLCAiTFFEIiksIHJlc3BfdmFyID0gIlNQWSIsIHN0YXJ0X2RhdGUgPSAiMjAxMi0wMS0wMSIsIGVuZF9kYXRlID0gIjIwMTYtMTItMzEiLCBudmFsID0gMjUwLCBudGVzdCA9IDI1MCwgbG93X20gPSAxLCBoaWdoX20gPSAyMywgbG93X3AgPSAxLCBoaWdoX3AgPSAxMCwgdGF1ID0gMC4wMSwgcHJpbnRfbWRsID0gMSwgcHJpbnRfbXAgPSAxLCBwYXRoID0gIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfYWxsX0VURl9ydW5zLyIsIGZpbGVuYW1lID0gInZhcl8xcGNfMjAxNl9hbGxfZXRmLmNzdiIsIHV2X2xpc3QgPSB2YXJfMXBjXzIwMTZfdXNldGZbWzFdXSkKCiMgdmFyXzVwY18yMDE2X2FsbF9ldGYgPSBjYXZfc2ltdWwoYygiWExVIiwgIlhMUCIsICJYTFYiLCAiWExLIiwgIlhMWSIsICJYTEkiLCAiWExGIiwgIlhMQiIsICJYTEUiLCAiSlhJIiwgIktYSSIsICJJWEoiLCAiSVhQIiwgIklYTiIsICJSWEkiLCAiRVhJIiwgIklYRyIsICJNWEkiLCAiSVhDIiwgIlNIWSIsICJJRUYiLCAiVExUIiwgIkxRRCIpLCByZXNwX3ZhciA9ICJTUFkiLCBzdGFydF9kYXRlID0gIjIwMTItMDEtMDEiLCBlbmRfZGF0ZSA9ICIyMDE2LTEyLTMxIiwgbnZhbCA9IDI1MCwgbnRlc3QgPSAyNTAsIGxvd19tID0gMSwgaGlnaF9tID0gMjMsIGxvd19wID0gMSwgaGlnaF9wID0gMTAsdGF1ID0gMC4wNSwgcHJpbnRfbWRsID0gMSwgcHJpbnRfbXAgPSAxLCBwYXRoID0gIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfYWxsX0VURl9ydW5zLyIsIGZpbGVuYW1lID0gInZhcl81cGNfMjAxNl9hbGxfZXRmLmNzdiIsIHV2X2xpc3QgPSB2YXJfNXBjXzIwMTZfdXNldGZbWzFdXSkKCiMgdmFyXzEwcGNfMjAxNl9hbGxfZXRmID0gY2F2X3NpbXVsKGMoIlhMVSIsICJYTFAiLCAiWExWIiwgIlhMSyIsICJYTFkiLCAiWExJIiwgIlhMRiIsICJYTEIiLCAiWExFIiwgIkpYSSIsICJLWEkiLCAiSVhKIiwgIklYUCIsICJJWE4iLCAiUlhJIiwgIkVYSSIsICJJWEciLCAiTVhJIiwgIklYQyIsICJTSFkiLCAiSUVGIiwgIlRMVCIsICJMUUQiKSwgcmVzcF92YXIgPSAiU1BZIiwgc3RhcnRfZGF0ZSA9ICIyMDEyLTAxLTAxIiwgZW5kX2RhdGUgPSAiMjAxNi0xMi0zMSIsIG52YWwgPSAyNTAsIG50ZXN0ID0gMjUwLCBsb3dfbSA9IDEsIGhpZ2hfbSA9IDIzLCBsb3dfcCA9IDEsIGhpZ2hfcCA9IDEwLHRhdSA9IDAuMTAsIHByaW50X21kbCA9IDEsIHByaW50X21wID0gMSwgcGF0aCA9ICIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2FsbF9FVEZfcnVucy8iLCBmaWxlbmFtZSA9ICJ2YXJfMTBwY18yMDE2X2FsbF9ldGYuY3N2IiwgdXZfbGlzdCA9IHZhcl8xMHBjXzIwMTZfdXNldGZbWzFdXSkKYGBgCgojIENvbmNsdXNpb25zIGFuZCBGdXR1cmUgV29yawoKVGhlIHByb2JsZW0gb2YgaG93IHRvIHByZWRpY3QgYSBsb3cgcXVhbnRpbGUgb2YgYSBzdG9jaydzIGxvZyByZXR1cm4gd2hlbiB0aGUgdHJhaW5pbmcgc2FtcGxlIGlzIHN1YnN0YW50aWFsbHkgZGlmZmVyZW50IHRoYW4gdGhlIHRlc3Qgc2NlbmFyaW8gaXMgYW4gZW5vcm1vdXNseSBkaWZmaWN1bHQgcHJvYmxlbS4gQWxtb3N0IGF4aW9tYXRpY2FsbHksIHRoZSBkaXN0cmlidXRpb24gaXMgbm9uc3RhdGlvbmFyeSBvdmVyIHRpbWUuIEhvdyBpcyBpdCBwb3NzaWJsZSB0byBwcmVkaWN0IHRoZSByZXR1cm4gb2YgYW4gaW5kZXggbGlrZSB0aGUgUyZQNTAwIGR1cmluZyBhIHBlcmlvZCBvZiBtYXJrZXQgdHVybW9pbCBzdWNoIGFzIHRoZSBncmVhdCByZWNlc3Npb24/IFdoaWxlIHRoZSBDQVZpYVIgbW9kZWwgcGVyZm9ybXMgY29tcGFyYXRpdmVseSB3ZWxsIGR1cmluZyB0aW1lcyBvZiBzdHJlc3MsIGl0IHBlcmZvcm1zIGFib3V0IHRoZSBzYW1lIGFzIHRoZSBtdWx0aXZhcmlhdGUgbW9kZWwgZHVyaW5nIG1vcmUgYmVuaWduIGVjb25vbWljIHBlcmlvZHMuCgpUaGlzIGNvbmNsdXNpb24gZHJhd24gZnJvbSB0aGUgYWJvdmUgcmVzdWx0cyBtaWdodCBzdXBwb3J0IHRoZSBub3Rpb24gb2YgY29tYmluaW5nIHRoZSB0d28gbW9kZWxzIGluIHNvbWUgc29ydCBvZiBhIG1peHR1cmUgbW9kZWwgLSBhaW1pbmcgdG8gdXNlIHRoZSBiYXNrZXQgb2YgRVRGcyBkdXJpbmcgZ29vZCB0aW1lcywgYW5kIHVzZSB0aGUgQ0FWaWFSIEFSTUEgc3BlY2lmaWNhdGlvbiBkdXJpbmcgYmFkIHRpbWVzLiBUaGUgYXBwcm9hY2ggb2YgdXNpbmcgRVRGcyBhbGxvd3MgYSBwcmVkaWN0aW9uIGJhc2VkIG9uIGZvcndhcmQtbG9va2luZyBleHBlY3RhdGlvbnMgb2YgZnVuZGFtZW50YWwgZmFjdG9ycy4gSW5kZWVkLCBFVEZzIGFyZSBqdXN0IGJhc2tldHMgb2YgaW5kaXZpZHVhbCBzdG9ja3Mgb3IgYm9uZHMsIGFuZCB0aG9zZSBzZWN1cml0aWVzIGFyZSAoaW4gdGhlb3J5KSBiYXNlZCBvbiByYXRpb25hbCBleHBlY3RhdGlvbnMgYWJvdXQgZnV0dXJlIHJlc291cmNlcywgbWFya2V0IGNvbmRpdGlvbnMsIGV0YyAtIHRoZSBtaWNyb2ZvdW5kYXRpb25zIG9mIHdoYXQgZHJpdmVzIG91ciBlY29ub215LiBUaGUgQVJNQSBzcGVjaWZpY2F0aW9uLCB3aGlsZSBwcmFjdGljYWxseSBhbmQgc3RhdGlzdGljYWxseSBzb3VuZCwgaXMgY29udHJhZGljdGVkIGJ5IGVjb25vbWljIHRoZW9yeSBhbmQgcHJhY3RpY2UgLSB0aGUgd2VhayBmb3JtIG9mIHRoZSBlZmZpY2llbnQgbWFya2V0IGh5cG90aGVzaXMgc3RhdGVzIHRoYXQgaXQgaXMgaW1wb3NzaWJsZSB0byBmb3JlY2FzdCBmdXR1cmUgdmFsdWVzIG9mIGFzc2V0IHByaWNlcyB1c2luZyBwYXN0IHZhbHVlcy4gQnV0IHBlcmhhcHMgdGhpcyB2aWV3IGlzIGluY29tcGxldGUuCgpBbnkgbW9kZWwgdGhhdCBhdHRlbXB0cyB0byBjYXB0dXJlIHJlbGF0aW9uc2hpcHMgaW4gdGhlIHJlYWwgd29ybGQgd2lsbCBvbmx5IHdvcmsgdW50aWwgYW4gb21pdHRlZCB2YXJpYWJsZSBpcyBmb3VuZC4gVGhlIGVsZWdhbmNlIG9mIHRoZSBtdWx0aXZhcmlhdGUgQ0FWaWFSIG1vZGVsIGlzIHRoYXQgaXQgcHJvdmlkZXMgaW5zaWdodCBpbnRvIHdoeSBhIHByZWRpY3Rpb24gaXMgd3Jvbmc7IHRoZSBjaGFuZ2UgaW4gdGhlIGFuZ2xlIGJldHdlZW4gcmVzdWx0YW50IHZlY3RvcnMgaXMgYSBzZW5zaWJsZSBtZWFzdXJlbWVudCBvZiBlY29ub21pYyBjaGFuZ2Vwb2ludHMgKENIQU5HRSkuIEhvd2V2ZXIsIGVycm9ycyBpbiB0aGUgd29ybGQgYXJlIGNvc3RseSwgYW5kIGl0J3Mgd2lzaGZ1bCB0aGlua2luZyB0byBzYXkgdGhhdCBleHBsYWluaW5nIHdoeSB0aGUgZXJyb3Igb2NjdXJyZWQgaXMgc3VmZmljaWVudC4KCkFzIHN1Y2gsIGZvciBmdXR1cmUgd29yayBpdCdzIHdvcnRoIGV4cGxvcmluZyB0aGUgbm90aW9uIG9mIHdlaWdodGluZyBhbiBBUk1BLWFwcHJvYWNoIG1vcmUgaGVhdmlseSB3aGVuIHByZWRpY3Rpb25zIHVzaW5nIGZ1bmRhbWVudGFscyB3ZXJlIHRvbyBoaWdoLCB0aGVuIG5vdCBvbmx5IHdvdWxkIHRoaXMgYWZ0ZXItdGhlLWZhY3QgcmVjb2duaXRpb24gYmUgYWNoaWV2ZXMsIGJ1dCBhbHNvIGEgaGllcmFyY2hpY2FsIG1vZGVsIHRoYXQgY2FwdHVyZXMgZnVuZGFtZW50YWwgcmVsYXRpb25zaGlwcyBpbiB0aGUgZWNvbm9teSBhbmQgcG90ZW50aWFsbHkgY2hhbmdlcyBvdXIgdW5kZXJzdGFuZGluZyBvZiBhc3NldCBwcmljZXMgaW4gZ2VuZXJhbCAtIGEgc3ludGhlc2lzIGJldHdlZW4gS2V5bmVzJyBhbmltYWwgc3Bpcml0cyBkdXJpbmcgYSB0aW1lIG9mIHNldmVyZSBjcmlzaXM7IHdoZXJlIGEgbW9kZWwgY2Fubm90IGV4cGxhaW4gc2hpZnRzLCBhbmQgYSBtb3JlIHJhdGlvbmFsIHdvcmxkIHRoYXQgZXhwbGFpbnMgb3RoZXIgcGVyaW9kcy4gSW4gYWRkaXRpb24gdG8gc2lnbmlmaWNhbnQgcHJlZGljdGl2ZSBwb3dlciBiZWNhdXNlIG9mIHRoZSBzd2l0Y2hpbmcgYmV0d2VlbiB0aGUgdHdvIHdvcmxkcywgdGhlcmUncyBhbHNvIGFuIGVsZWdhbnQgZXhwbGFuYXRpb247IGEgd2F5IHRvIGV4cGxhaW4gY2hhbmdlcyBpbiB0aGUgdXNlZnVsbmVzcyBvZiB0aGUgdW5kZXJwaW5uaW5ncyBpbiB0aGUgZWNvbm9teS4gQmVjYXVzZSBvZiB0aGUgZmxleGliaWxpdHkgb2YgdGhlIG1vZGVsLCBpdCdzIGVudGlyZWx5IHBvc3NpYmxlIHRoYXQgYSB3aG9sZSBnYW11dCBvZiB2YXJpYWJsZXMgY291bGQgYmUgdG9zc2VkIGluIGFuZCBiYWNrdGVzdGVkIHRvIHdoZW4gImNoYW5nZXBvaW50cyIgb2NjdXJyZWQuIAoKQWRkaXRpb25hbCBmdXR1cmUgd29yayBpbnZvbHZlcyBkZXZlbG9waW5nIHRoZW9yZXRpY2FsIGd1YXJhbnRlZXMgb24gdGhlIHBhcmFtZXRlcnMgaW4gdGhlIG11bHRpdmFyaWF0ZSBDQVZpYVIgbW9kZWwuIE9uZSBhZHZhbnRhZ2Ugb2YgYm90aCB0aGUgZGlmZnVzaW9uIGluZGV4IG1vZGVsIGFuZCB0aGUgQ0FWaWFSIG1vZGVsIGlzIHRoYXQgYm90aCBoYXZlIHRoZW9yZW1zIGFib3V0IGFzeW1wdG90aWMgbm9ybWFsaXR5IGFuZCBjb25zaXN0ZW5jeSBbQ09ORklSTV0uCgoKIyBDb2RlIEFwcGVuZGl4CgpgYGB7ciByZWYubGFiZWw9a25pdHI6OmFsbF9sYWJlbHMoKSwgZWNobyA9IFQsIGV2YWwgPSBGfQpgYGAKCiMgTGl0ZXJhdHVyZSBDaXRlZAo=